How do I set different headers for Cloudflare Pages paths?

The Citead team, updated

In short. Use a _headers file with URL patterns and indented header lines; all matching rules contribute headers, with repeated values joined by commas.

Definition: Cloudflare Pages path header rules associate a URL pattern with response header names and values in a plain text _headers file. As of 17 October 2026, Cloudflare documents these rules for static asset responses, with every matching rule contributing its headers.

Key facts

Where does the file go, and how are paths written?

Cloudflare's headers documentation places _headers, without a file extension, in the project's static asset directory. With a framework, public/ or static/ commonly supplies files copied into the build output. Without a framework, the file can go directly in the build output directory. Pages parses the file rather than serving it as an asset.

Each block starts with a URL or URL pattern, followed by indented Name: value lines. These rules are adapted from Cloudflare's example:

/secure/page
  X-Frame-Options: DENY

/static/*
  Access-Control-Allow-Origin: *

https://myproject.pages.dev/*
  X-Robots-Tag: noindex

The /secure/page block targets that path. The /static/* block targets paths beginning with /static/. The absolute URL block also targets the specified hostname. Absolute patterns must begin with https and omit a port; matching ignores the incoming request's protocol and port.

How do wildcards and placeholders differ?

A splat is the * wildcard, which greedily matches all characters. Cloudflare's path matching documentation allows a single splat per URL and exposes its captured value as :splat inside a header value.

A named placeholder starts with a colon followed by a letter. Its name contains letters, digits or underscores. In a path, the placeholder stops at /; in a hostname, it stops at . or /. Cloudflare permits each named placeholder to be referenced once and gives this example:

/movies/:title
  x-movie-name: You are watching ":title"

Here, :title supplies the captured path segment to the response header. Cloudflare also demonstrates a hostname placeholder in a rule whose header value reuses the project name:

https://:project.pages.dev/*
  Access-Control-Allow-Origin: https://staging.:project.pages.dev/

What happens when header rules overlap?

Cloudflare's header matching rules give a request every matching block's headers. When the same header appears twice, Pages joins the values with a comma separator. The documentation's overlapping path and hostname example produces X-Robots-Tag: nosnippet, noindex for https://myproject.pages.dev/static/styles.css.

A removal line starts with an exclamation mark followed by a space. Cloudflare shows this configuration for removing a header added by a broader rule:

/*
  Content-Security-Policy: default-src 'self';

/*.jpg
  ! Content-Security-Policy

The broader block adds Content-Security-Policy; the image rule removes it for matching JPEG paths.

FAQ

How many header rules can I define?

Cloudflare's headers reference permits up to 100 rules. Each line has a 2,000 character limit, including spacing, header name and value.

Why does a matching path receive no custom header from this file?

If your response is generated by Pages Functions, the same documentation's Functions exclusion applies even when the URL matches _headers. Attach the custom headers within the Functions code for those responses.

What if my path also matches a redirect?

Cloudflare's redirect and header matching guidance gives the redirect priority. Check your _redirects file when investigating a matching path that redirects.

Sources

  1. Cloudflare, "Headers", updated 25 August 2026
  2. Cloudflare, "Redirects", updated 25 August 2026
  3. Cloudflare, "Add custom HTTP headers", updated 21 April 2026

Check how a page reads to answer engines. Open the GEO score analyzer

Test a page and see what to fix first

The analysis usually takes less than 10 seconds and needs no account.

400,000+ pages scored in the public benchmark