Gateway HTTP policies with Allow actions can modify the headers of matching requests before they reach their destination. You can add dynamic values to set headers to forward information like user identity, source IP, and other inputs to upstream services, enforce SaaS tenant control, strip internal headers, override header content.
Header manipulation requires TLS decryption, because HTTP headers are only visible on traffic which Gateway can decrypt.
Gateway supports three header operations on HTTP policies. When a request matches an Allow policy with header operations configured, Gateway applies them in the following order:
- Delete - Remove headers from the request.
- Overwrite - Overwrite headers on the request. Headers with matched names will have their values overwritten. If the header does not exist, it is created.
- Add - Append headers to the request. If the header already exists, the added value is appended to the existing value.
You can configure up to 20 header operations per policy. Header names are limited to 256 bytes, and header values are limited to 4 KB.
Adding a header appends a value to the request. If the header already exists, the value is added alongside the existing value rather than replacing it.
Overwriting a header overwrites any existing value. If the header does not already exist on the request, it is created. Use this operation when you need to guarantee a specific header value regardless of what the client sent.
Deleting a header removes it from the request entirely. If the header does not exist, the operation has no effect.
Header values can include dynamic variables that Gateway resolves at request time using identity, device, and network context from the current session. Dynamic variables use the @{...} syntax and can be mixed with static text in the same value.
For example, a header value of user-@{identity.email} resolves to user-jdoe@example.com at request time.
The following dynamic variables are available:
| Variable | Description |
|---|---|
@{identity.email} |
User's email address from the identity provider. |
@{identity.name} |
User's display name from the identity provider. |
@{identity.id} |
User's Cloudflare identity UUID. |
@{identity.groups} |
User's identity provider group memberships. |
@{identity.SAML} |
User's SAML attributes from the identity provider if configured. |
@{identity.OIDC} |
User's OIDC claims from the identity provider if configured. |
@{source.ip} |
Source IP address of the user's connection as seen in Gateway. |
@{destination.ip} |
Destination IP address of the request. |
@{device.id} |
Cloudflare One Client device UUID. |
@{device.posture} |
Device posture check results (serialized as a JSON string). |
Dynamic variables require an active identity session. If Gateway cannot resolve a variable (for example, the user is not authenticated), the variable is replaced with a warning string such as cf-unresolved or cf-invalid, and a warning is added to the HTTP log.
To create an HTTP policy with header operations:
- In the Cloudflare One dashboard ↗, go to Traffic policies > Firewall policies > HTTP.
- Select Add a policy.
- Build an expression to match the traffic you want to modify.
- In Action, select Allow.
- Under Modify request headers, select Add or Overwrite to add or overwrite headers, or select Remove to delete a header.
- For Add and Overwrite operations, enter the header name and value. To use a dynamic variable, enter the
@{...}syntax in the value field, or select the{}button to see the list of available values. For Remove operations, enter only the header name. - Save your policy.
To create an HTTP policy with header operations via the API, include add_headers, set_headers, and delete_headers in the rule_settings object.
curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \
--header "Authorization: Bearer {api_token}" \
--header "Content-Type: application/json" \
--data '{
"name": "Forward identity headers",
"action": "allow",
"enabled": true,
"filters": ["http"],
"traffic": "any(http.request.domains[*] in {\"app.example.com\"})",
"rule_settings": {
"add_headers": {
"X-User-Email": ["@{identity.email}"],
"X-User-Groups": ["@{identity.groups}"]
},
"set_headers": {
"X-Forwarded-User": ["@{identity.email}"]
},
"delete_headers": ["X-Debug-Token", "X-Internal-Only"]
}
}'The rule_settings fields for header manipulation are:
| Field | Type | Description |
|---|---|---|
add_headers |
map<string, array<string>> |
Headers to append. Each key is a header name, each value is a list of values to add. |
set_headers |
map<string, array<string>> |
Headers to overwrite. Each key is a header name, each value is a list of values to set. |
delete_headers |
array<string> |
Header names to remove from the request. |
A single header value can contain a mix of static text and dynamic variables. For example:
{
"add_headers": {
"X-Request-Context": ["user=@{identity.email}, device=@{device.id}, src=@{source.ip}"]
}
}If you save a HAR (HTTP Archive) file from a browser to analyze your web traffic, custom headers defined with Gateway will not appear in the file. This is because Gateway injects the header after the request leaves the browser.
To verify Gateway is applying a custom header:
-
In your policy with custom headers, add a selector to match traffic for HTTPBin ↗, an open-source site for testing HTTP requests. For example:
Selector Operator Value Logic Action Untrusted certificate action Application in Google Workspace Or Allow Block Domain in httpbin.org -
On your device, go to
httpbin.org/anything↗. Your custom header will appear in the list of headers. -
(Optional) Remove the HTTPBin expression from your policy.
Tenant control allows your users to access corporate SaaS applications while blocking access to personal accounts on the same service. For example, you can allow access to your company's Google Workspace while blocking personal Gmail logins.
Gateway implements tenant control by injecting custom HTTP headers into matching requests. These headers tell the SaaS application which tenant (organization) is authorized. If the user attempts to authenticate with a personal account, the SaaS application reads the header and rejects the request.
Microsoft 365
Microsoft 365 tenant control requires two policies. When you order your policies, make sure they follow order of precedence.
| Precedence | Selector | Operator | Value | Action | Untrusted certificate action |
|---|---|---|---|---|---|
| 1 | Domain | is | login.live.com |
Allow | Block |
| Custom header name | Custom header value |
|---|---|
Sec-Restrict-Tenant-Access-Policy |
restrict-msa |
| Precedence | Selector | Operator | Value | Action | Untrusted certificate action |
|---|---|---|---|---|---|
| 2 | Application | in | Microsoft Office365 | Allow | Block |
| Custom header name | Custom header value |
|---|---|
Restrict-Access-To-Tenants, Restrict-Access-Context |
Your organization's domain |
For more information, refer to the Microsoft Entra ID documentation ↗.
Google Workspace
| Selector | Operator | Value | Action | Untrusted certificate action |
|---|---|---|---|---|
| Application | in | Google Workspace | Allow | Block |
| Custom header name | Custom header value |
|---|---|
X-GoogApps-Allowed-Domains |
Your organization's domain |
For more information, refer to the Google Workspace documentation ↗.
Slack
| Selector | Operator | Value | Action | Untrusted certificate action |
|---|---|---|---|---|
| Application | in | Slack | Allow | Block |
| Custom header name | Custom header value |
|---|---|
X-Slack-Allowed-Workspaces-Requester, X-Slack-Allowed-Workspaces |
Your organization's workspace |
For more information, refer to the Slack documentation ↗.
Dropbox
| Selector | Operator | Value | Action | Untrusted certificate action |
|---|---|---|---|---|
| Application | in | Dropbox | Allow | Block |
| Custom header name | Custom header value |
|---|---|
X-Dropbox-allowed-Team-Ids |
Your organization's ID |
For more information, refer to the Dropbox documentation ↗.
ChatGPT
| Selector | Operator | Value | Action | Untrusted certificate action |
|---|---|---|---|---|
| Application | in | ChatGPT | Allow | Block |
| Custom header name | Custom header value |
|---|---|
Chatgpt-Allowed-Workspace-Id |
Your organization's workspace ID |
For more information, refer to the OpenAI documentation ↗.
Claude
| Selector | Operator | Value | Action | Untrusted certificate action |
|---|---|---|---|---|
| Application | in | Claude | Allow | Block |
| Custom header name | Custom header value |
|---|---|
anthropic-allowed-org-ids |
Your organization's UUID |
To allow access from multiple organizations, enter a comma-separated list of UUIDs with no spaces (for example, <org-uuid-1>,<org-uuid-2>).
You can find your organization UUID in Settings > Account > Organization ID on claude.ai ↗.
For more information, refer to the Claude documentation ↗.
You can use dynamic header values to forward user identity information to your upstream applications without requiring those applications to integrate with Cloudflare Access directly.
| Header name | Header value |
|---|---|
X-User-Email |
@{identity.email} |
X-User-Name |
@{identity.name} |
X-User-Groups |
@{identity.groups} |
X-Source-IP |
@{source.ip} |
Your upstream application can read these headers to identify the user, enforce authorization logic, or populate audit logs.
To prevent clients from spoofing internal headers, use the delete operation to remove headers before forwarding the request, then use the add or set operation to re-inject them with verified values.
curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \
--header "Authorization: Bearer {api_token}" \
--header "Content-Type: application/json" \
--data '{
"name": "Replace internal headers",
"action": "allow",
"enabled": true,
"filters": ["http"],
"traffic": "any(http.request.domains[*] in {\"internal.example.com\"})",
"rule_settings": {
"delete_headers": ["X-Internal-User"],
"set_headers": {
"X-Internal-User": ["@{identity.email}"]
}
}
}'You can include custom headers in an HTTP policy to allow your users through Cloudflare WAF. This is useful for allowing only Cloudflare One Client users through your WAF.
-
Create an Allow policy for an internal domain behind your WAF with a custom header.
Selector Operator Value Action Domain in internalapp.comAllow Custom header name Custom header value X-Example-Headerexample-value -
In Cloudflare WAF, create a custom rule to require the same HTTP header.
You can configure Browser Isolation to send custom headers. This is useful for implementing tenant control for isolated SaaS applications or sending arbitrary custom request headers to isolated websites.
To use custom headers with Browser Isolation, create two HTTP policies targeting the same domain or application group. For example, you can create policies for HTTPBin ↗, an open-source site for testing HTTP requests:
-
Create an Isolate policy for
httpbin.org.Selector Operator Value Action Domain in httpbin.orgIsolate -
Create an Allow policy for
httpbin.orgwith a custom header.Selector Operator Value Action Domain in httpbin.orgAllow Custom header name Custom header value Example-Headerexample-value -
Go to
httpbin.org/anything↗. Cloudflare will render the site in an isolated browser. Your custom header will appear in the list of headers.