---
title: Headers
description: Learn about default and custom headers for Workers static assets, including Cache-Control, ETag, and Content-Type behavior.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/workers/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Headers

## Default headers

When serving static assets, Workers will attach some headers to the response by default. These are:

* **`Content-Type`**  
A `Content-Type` header is attached to the response if one is provided during [the asset upload process](https://developers.cloudflare.com/workers/static-assets/direct-upload/). [Wrangler](https://developers.cloudflare.com/workers/wrangler/commands/general/#deploy) automatically determines the MIME type of the file, based on its extension.
* **`Cache-Control: public, max-age=0, must-revalidate`**  
Sent when the request does not have an `Authorization` or `Range` header, this response header tells the browser that the asset can be cached, but that the browser should revalidate the freshness of the content every time before using it. This default behavior ensures good website performance for static pages, while still guaranteeing that stale content will never be served.
* **`ETag`**  
This header complements the default `Cache-Control` header. Its value is a hash of the static asset file, and browsers can use this in subsequent requests with an `If-None-Match` header to check for freshness, without needing to re-download the entire file in the case of a match.
* **`CF-Cache-Status`**  
This header indicates whether the asset was served from the cache (`HIT`) or not (`MISS`).[1](#user-content-fn-1)

Cloudflare reserves the right to attach new headers to static asset responses at any time in order to improve performance or harden the security of your Worker application.

## 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 Workers 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 [static assets directory](https://developers.cloudflare.com/workers/static-assets/binding/#directory).

Headers defined in the `_headers` file override what Cloudflare ordinarily sends.

Warning

Custom headers defined in the `_headers` file are not applied to responses generated by your Worker code, even if the request URL matches a rule defined in `_headers`. If you use a server-side rendered (SSR) framework, have configured `assets.run_worker_first`, or otherwise use a Worker script, you will likely need to attach any custom headers you wish to apply directly within that Worker script.

### 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://myworker.mysubdomain.workers.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 X-Content-Type-Options: nosniff Referrer-Policy: no-referrer                       |
| https://custom.domain/static/image.jpg                     | Access-Control-Allow-Origin: \* X-Robots-Tag: nosnippet                                                  |
| https://myworker.mysubdomain.workers.dev/home              | X-Robots-Tag: noindex                                                                                    |
| https://myworker.mysubdomain.workers.dev/secure/page       | X-Frame-Options: DENY X-Content-Type-Options: nosniff Referrer-Policy: no-referrer X-Robots-Tag: noindex |
| https://myworker.mysubdomain.workers.dev/static/styles.css | Access-Control-Allow-Origin: \* 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](https://developers.cloudflare.com/workers/static-assets/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 Worker, 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. Note that the CORS specification only allows \`\*\`, \`null\`, or an exact origin as valid \`Access-Control-Allow-Origin\` values — wildcard patterns within origins are not supported. To allow CORS from specific [preview URLs](https://developers.cloudflare.com/workers/configuration/previews/), you will need to handle this dynamically in your Worker code rather than through the \`\_headers\` file.

##### Prevent your workers.dev URLs showing in search results

[Google ↗](https://developers.google.com/search/docs/advanced/robots/robots%5Fmeta%5Ftag#directives) 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 `\*.\*.workers.dev` URLs from being indexed, add the following to your `_headers` file:

```

https://:version.:subdomain.workers.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

Warning

If you are server-side rendering (SSR) or using a Worker to generate responses in any other way and wish to attach security headers, the headers should be sent from the Worker's `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 ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Frame-Options) header.

[X-Content-Type-Options: nosniff ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Content-Type-Options) prevents browsers from interpreting a response as any other content-type than what is defined with the `Content-Type` header.

[Referrer-Policy ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/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 ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Permissions-Policy) header (recently renamed from `Feature-Policy`).

If you need fine-grained control over your application's content, the [Content-Security-Policy ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/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';


```

## Footnotes

1. Due to a technical limitation that we hope to address in the future, the `CF-Cache-Status` header is not always entirely accurate. It is possible for false-positives and false-negatives to occur. This should be rare. In the meantime, this header should be considered as returning a "probabilistic" result. [↩](#user-content-fnref-1)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers/","name":"Workers"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers/static-assets/","name":"Static Assets"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers/static-assets/headers/","name":"Headers"}}]}
```
