Headers and Redirects Generator for Netlify
Netlify reads two small text files at deploy time. The _headers file attaches response headers to path patterns, and the _redirects file maps old paths to new destinations. This page builds both at once. Pick a security preset or type your own header rows, add redirect lines with a status code, and copy each file when it looks right. Nothing you type leaves the browser.
Build _headers and _redirects Side by Side
Headers file (_headers)
Set the path presets apply to, choose a preset, or add one header per row. Rows that share a path come out as one block.
Redirects file (_redirects)
One rule per row. The hint line below explains whatever status is selected in the last row you touched.
Content-Security-Policy helper
Compose one CSP value with a self default, frame protection, and optional extras, then paste it into a header row.
How It Works
A _headers file is a list of blocks. Each block opens with a path or pattern, then lists headers under it with a two-space indent and a colon between name and value. The pattern /* applies to every route on the site, while /assets/* reaches only that folder. The builder here groups rows that share a path into a single block, so the indentation comes out correct without hand editing.
A _redirects file is one rule per line with three fields: source path, destination, and status code. Netlify scans the file top to bottom and the first matching line wins, so order matters when patterns overlap. A destination can be another path on the site or a full URL, and a splat segment such as :splat carries the wildcard part of the source into the destination.
The CSP helper builds a single Content-Security-Policy value from a self default plus base-uri, form-action, and frame-ancestors, with optional connect-src and upgrade-insecure-requests flags. Validation runs beside the output rather than in front of it, so amber notes about paths, header names, or redirect loops never stop the file text from updating.
| Status | Kind | Typical use |
|---|---|---|
| 200 | Rewrite | Serve the destination content under the source path |
| 301 / 308 | Permanent | Finished moves; 308 keeps the request method |
| 302 / 303 / 307 | Temporary | A/B tests and short-lived swaps; 307 keeps the method |
| 404 / 410 | Removal | Retire a path; 410 tells crawlers to drop it sooner |
Before and After
/* X-Content-Type-Options nosniff
/* Referrer-Policy strict-origin
/* X-Frame-Options DENY /*
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
X-Frame-Options: DENY old page goes to new page (301?)
blog moved under news, keep the rest /old /new 301
/blog/* /news/:splat 301 Use Cases
| Scenario | What you enter | File you get |
|---|---|---|
| Security pass before launch | Baseline preset at /* | _headers with six security headers |
| Moving a docs section | /docs/* to /manual/:splat at 301 | _redirects line with a splat passthrough |
| JSON API with CORS | API preset at /api/* | _headers with content type and cache control |
| Retiring a page | Source path with status 410 | _redirects line that drops the URL from crawlers |
Common Mistakes
- Skipping the two-space indent in _headers. Header lines that sit at the same column as the path are read as a new block instead of a header.
- Using 301 for a URL you still edit. Browsers cache permanent moves for a long time, so ship a 307 during the testing window and swap to 301 after.
- Leaving the source path without a leading slash. /old and old match different sets of requests, and the bare form is dropped by the builder.
- Writing a redirect where the source and destination are the same, which creates a loop the browser reports as a redirect error.
Best Practices
- Run the baseline preset at /* first, then add path blocks for /api/* or /assets/* when those routes need different values.
- Keep one header per row in the builder and let the grouping merge rows that share a path, which keeps the block order easy to read.
- Pick 308 when a POST must keep its method across a permanent move, and 307 for the temporary case; read the hint line after each status change.
- Put the most specific path patterns before wildcard blocks, since the first matching line in _redirects wins regardless of pattern size.
Frequently Asked Questions
What files does Netlify read for custom headers and redirects?
Netlify reads two plain text files from the publish directory. The _headers file maps path patterns to response headers, and the _redirects file maps source paths to destinations with a status code. Both files deploy with the rest of the site and need no build step.
How are path patterns matched in the _headers file?
Each block starts with a path such as /* or /assets/*. A plain path matches that exact location, and an asterisk matches any run of characters after it. Several blocks can target the same path, and the order of the blocks decides which one applies when two patterns both match a request.
Which status codes should a redirect rule use?
301 and 308 are permanent, so browsers and crawlers cache them for a long time. 302, 303, and 307 are temporary and leave the original path as the main target. A 200 acts as a rewrite, serving the destination content under the source path. 404 and 410 remove a path without forwarding it.
What does the security header preset set?
The baseline preset fills in X-Content-Type-Options, Referrer-Policy, X-Frame-Options, Permissions-Policy, Content-Security-Policy, and Upgrade-Insecure-Requests. Other presets cover JSON APIs, immutable assets, short-lived HTML documents, and HTTPS-only responses. Applying a preset replaces the rows below it at the chosen path.
Does the generator merge rows that share a path?
Yes. The builder groups rows with the same path into one block, so three headers typed at /* come out as a single block with three indented lines. Rows with different paths become separate blocks. Blank paths or blank header names stay out of the output while the amber list points them out.
How does the CSP helper differ from the preset headers?
The CSP helper composes a Content-Security-Policy value from default-src self, base-uri, form-action, and frame-ancestors, then optionally adds connect-src and upgrade-insecure-requests. Copy that single header value into a Content-Security-Policy row or into your server configuration.
Do my paths and header values leave the browser?
No request runs when you type a path or press Apply preset. The rows are read from the page, the file text is assembled by functions bundled with the page, and the copy button writes to the local clipboard only. Closing the tab discards every row.