Headers
Last updated Aug 25, 2026
Custom headers
The default response headers served on static asset responses can be overridden, removed, or added to, by creating a plain text file called _headers without a file extension, in the static asset directory of your project. This file will not itself be served as a static asset, but will instead be parsed by Cloudflare Pages and its rules will be applied to static asset responses.
If you are using a framework, you will often have a directory named public/ or static/, and this usually contains deploy-ready assets, such as favicons, robots.txt files, and site manifests. These files get copied over to a final output directory during the build, so this is the perfect place to author your _headers file. If you are not using a framework, the _headers file can go directly into your build output directory.
Headers defined in the _headers file override what Cloudflare ordinarily sends.
Caution
Custom headers defined in the _headers file are not applied to responses generated by Pages Functions, even if the request URL matches a rule defined in _headers. If you use a server-side rendered (SSR) framework, or Pages Functions (with either a folder of functions/ or an "advanced mode" _worker.js), you will likely need to attach any custom headers you wish to apply directly within that Pages Functions code.
Attach a header
Header rules are defined in multi-line blocks. The first line of a block is the URL or URL pattern where the rule's headers should be applied. On the next line, an indented list of header names and header values must be written:
[url]
[name]: [value]
Using absolute URLs is supported, though be aware that absolute URLs must begin with https and specifying a port is not supported. _headers rules ignore the incoming request's port and protocol when matching against an incoming request. For example, a rule like https://example.com/path would match against requests to other://example.com:1234/path.
You can define as many [name]: [value] pairs as you require on subsequent lines. For example:
# This is a comment
/secure/page
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: no-referrer
/static/*
Access-Control-Allow-Origin: *
X-Robots-Tag: nosnippet
https://myproject.pages.dev/*
X-Robots-Tag: noindex
An incoming request which matches multiple rules' URL patterns will inherit all rules' headers. Using the previous _headers file, the following requests will have the following headers applied:
| Request URL | Headers |
|---|---|
https://custom.domain/secure/page |
X-Frame-Options: DENY <br> X-Content-Type-Options: nosniff <br> Referrer-Policy: no-referrer |
https://custom.domain/static/image.jpg |
Access-Control-Allow-Origin: * <br> X-Robots-Tag: nosnippet |
[https://myproject.pages.dev/home ↗︎](https://myproject.pages.dev/home) |
X-Robots-Tag: noindex |
[https://myproject.pages.dev/secure/page ↗︎](https://myproject.pages.dev/secure/page) |
X-Frame-Options: DENY <br> X-Content-Type-Options: nosniff <br> Referrer-Policy: no-referrer <br> X-Robots-Tag: noindex |
[https://myproject.pages.dev/static/styles.css ↗︎](https://myproject.pages.dev/static/styles.css) |
Access-Control-Allow-Origin: * <br> X-Robots-Tag: nosnippet, noindex |
You may define up to 100 header rules. Each line in the _headers file has a 2,000 character limit. The entire line, including spacing, header name, and value, counts towards this limit.
If a header is applied twice in the _headers file, the values are joined with a comma separator.
Detach a header
You may wish to remove a default header or a header which has been added by a more pervasive rule. This can be done by prepending the header name with an exclamation mark and space (! ).
/*
Content-Security-Policy: default-src 'self';
/*.jpg
! Content-Security-Policy
Match a path
The same URL matching features that _redirects offers is also available to the _headers file. Note, however, that redirects are applied before headers, so when a request matches both a redirect and a header, the redirect takes priority.
Splats
When matching, a splat pattern — signified by an asterisk (*) — will greedily match all characters. You may only include a single splat in the URL.
The matched value can be referenced within the header value as the :splat placeholder.
Placeholders
A placeholder can be defined with :placeholder_name. A colon (:) followed by a letter indicates the start of a placeholder and the placeholder name that follows must be composed of alphanumeric characters and underscores (:[A-Za-z]\w*). Every named placeholder can only be referenced once. Placeholders match all characters apart from the delimiter, which when part of the host, is a period (.) or a forward-slash (/) and may only be a forward-slash (/) when part of the path.
Similarly, the matched value can be used in the header values with :placeholder_name.
/movies/:title
x-movie-name: You are watching ":title"
Examples
Cross-Origin Resource Sharing (CORS)
To enable other domains to fetch every static asset from your Pages project, the following can be added to the _headers file:
/*
Access-Control-Allow-Origin: *
This applies the Access-Control-Allow-Origin header to any incoming URL. To be more restrictive, you can define a URL pattern that applies to a *.pages.dev subdomain, which then only allows access from its staging branch's subdomain:
https://:project.pages.dev/*
Access-Control-Allow-Origin: https://staging.:project.pages.dev/
Prevent your workers.dev URLs showing in search results
Google ↗︎ and other search engines often support the X-Robots-Tag header to instruct its crawlers how your website should be indexed.
For example, to prevent your *.pages.dev and *.*.pages.dev URLs from being indexed, add the following to your _headers file:
https://:project.pages.dev/*
X-Robots-Tag: noindex
https://:version.:project.pages.dev/*
X-Robots-Tag: noindex
Configure custom browser cache behavior
If you have a folder of fingerprinted assets (assets which have a hash in their filename), you can configure more aggressive caching behavior in the browser to improve performance for repeat visitors:
/static/*
Cache-Control: public, max-age=31556952, immutable
Harden security for an application
Caution
If you are server-side rendering (SSR) or using Pages Functions to generate responses in any other way and wish to attach security headers, the headers should be sent from the Pages Functions' Response instead of using a _headers file. For example, if you have an API endpoint and want to allow cross-origin requests, you should ensure that your Worker code attaches CORS headers to its responses, including to OPTIONS requests.
You can prevent click-jacking by informing browsers not to embed your application inside another (for example, with an <iframe>) with a X-Frame-Options ↗︎ header.
X-Content-Type-Options: nosniff ↗︎ prevents browsers from interpreting a response as any other content-type than what is defined with the Content-Type header.
Referrer-Policy ↗︎ allows you to customize how much information visitors give about where they are coming from when they navigate away from your page.
Browser features can be disabled to varying degrees with the Permissions-Policy ↗︎ header (recently renamed from Feature-Policy).
If you need fine-grained control over your application's content, the Content-Security-Policy ↗︎ header allows you to configure a number of security settings, including similar controls to the X-Frame-Options header.
/app/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: no-referrer
Permissions-Policy: document-domain=()
Content-Security-Policy: script-src 'self'; frame-ancestors 'none';
Was this helpful?
YesNo
On this page
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/pages/configuration/headers/#page","headline":"Headers","description":"Set custom HTTP response headers for your Cloudflare Pages site using a _headers file.","url":"https://developers.cloudflare.com/pages/configuration/headers/","inLanguage":"en","image":"https://developers.cloudflare.com/pages/configuration/headers/og.png?v=0a4338c45fff84d6","dateModified":"2026-08-25","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
description: Deploy multiple Cloudflare Pages projects from a single monorepo repository. title: Monorepos image: https://developers.cloudflare.com/pages/configuration/monorepos/og.png?v=05fabe1e1b4dbd18
Documentation Index
Fetch the complete documentation index at: https://developers.cloudflare.com/pages/llms.txt
Use this file to discover all available pages before exploring further.
Docs