---
title: Argo Smart Routing
description: Route traffic across the fastest network paths to reduce latency and packet loss.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Argo Smart Routing

Speed up your global traffic with a single click

 Paid add-on 

Smart Shield

This functionality is now offered as part of Cloudflare's origin server safeguard, Smart Shield. [Learn more](https://developers.cloudflare.com/smart-shield/).

Argo Smart Routing detects real-time network issues and routes your web traffic across the most efficient network path, avoiding congestion.

This results in faster loading times, increased reliability, and reduced costs. These benefits are most apparent for users farthest from your origin server.

Learn more about the [benefits of Argo Smart Routing ↗](https://www.cloudflare.com/application-services/products/argo-smart-routing/).

Note

Enterprise customers can preview this product as a [non-contract service](https://developers.cloudflare.com/billing/understand/preview-services/), which provides full access, free of metered usage fees, limits, and certain other restrictions.

---

## Features

###  Analytics 

Argo Smart Routing includes comprehensive analytics to compare performance improvements with and without Argo enabled.

[ Use Analytics ](https://developers.cloudflare.com/argo-smart-routing/analytics/) 

---

## Related products

**[Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/)** 

Increase cache hit ratios to reduce requests to your origin server.

**[China Network](https://developers.cloudflare.com/china-network/)** 

Improve security and performance within mainland China.

**[Magic Transit](https://developers.cloudflare.com/magic-transit/)** 

Reduce latency and protect from DDoS attacks using the Cloudflare network.

---

## More resources

[Plans](https://www.cloudflare.com/plans/#overview) 

Compare available Cloudflare plans

[Pricing](https://dash.cloudflare.com/?to=/:account/:zone/traffic/) 

Explore pricing options for Argo in the dashboard

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/argo-smart-routing/","name":"Argo Smart Routing"}}]}
```

---

---
title: Get started
description: Learn how to enable Argo Smart Routing in the Cloudflare dashboard.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

Smart Shield

This functionality is now offered as part of Cloudflare's origin server safeguard, Smart Shield. [Learn more](https://developers.cloudflare.com/smart-shield/).

Argo Smart Routing speeds up your global traffic by routing requests across the fastest network paths available.

* [ Dashboard ](#tab-panel-6591)
* [ API ](#tab-panel-6592)

To enable [Argo Smart Routing ↗](https://dash.cloudflare.com/?to=/:account/:zone/traffic) in the dashboard:

1. In the Cloudflare dashboard, go to the **Argo Smart Routing** page.  
[ Go to **Argo Smart Routing** ](https://dash.cloudflare.com/?to=/:account/:zone/traffic)
2. For **Argo Smart Routing**, switch the toggle to **On**.
3. Provide your billing information.  
   * If you do not have a [billing profile](https://developers.cloudflare.com/billing/get-started/create-billing-profile/), enter your billing information.  
   * If you have a billing profile, confirm your billing information.

To enable or disable Argo Smart Routing with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/argo/subresources/smart%5Frouting/methods/edit/) request with the `value` parameter set to your desired setting (`"on"` or `"off"`).

You will need to already have a [billing profile](https://developers.cloudflare.com/billing/get-started/create-billing-profile/) on your account to enable Argo Smart Routing.

Note

Enterprise customers can preview this product as a [non-contract service](https://developers.cloudflare.com/billing/understand/preview-services/), which provides full access, free of metered usage fees, limits, and certain other restrictions.

## Billing

If Cloudflare mitigates attacks on your site - whether through DDoS protection, the WAF, or other mechanisms - that traffic will not be included in any charges for Argo Smart Routing.

Since this is a service with [usage-based billing](https://developers.cloudflare.com/billing/understand/usage-based-billing/), Cloudflare recommends that you set up usage-based billing notifications to avoid unexpected bills.

To set up those notifications:

1. In the Cloudflare dashboard, go to the **Notifications** page.  
[ Go to **Notifications** ](https://dash.cloudflare.com/?to=/:account/notifications)
2. On **Alert Type** of **Usage Based Billing**, click **Select**.
3. Fill out the following information:  
   * **Name**  
   * **Product**  
   * **Notification limit** (exact metric will vary based on product)  
   * **Notification email**  
Note  
Some plans also have access to alerts through [PagerDuty](https://developers.cloudflare.com/notifications/get-started/configure-pagerduty/) and [Webhooks](https://developers.cloudflare.com/notifications/get-started/configure-webhooks/).
4. Select **Save**.

## Enable Tiered Cache

[Cache](https://developers.cloudflare.com/cache/) works by storing a copy of website content at Cloudflare's data centers. [Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) organizes these data centers into a hierarchy based on location. This behavior allows Cloudflare to deliver content from data centers closest to your visitor.

When used together, Argo Smart Routing optimizes the network path between Cloudflare data centers and your origin, while Tiered Cache reduces the number of requests that reach your origin. For more information, refer to [Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/argo-smart-routing/","name":"Argo Smart Routing"}},{"@type":"ListItem","position":3,"item":{"@id":"/argo-smart-routing/get-started/","name":"Get started"}}]}
```

---

---
title: Analytics
description: View latency improvements and response time data for Argo Smart Routing.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Analytics

Cloudflare provides analytics to show the performance benefits of Argo Smart Routing.

You can access Argo analytics for your domain in the [Cloudflare dashboard ↗](https://dash.cloudflare.com/) at **Analytics** \> **Performance**. For information on all analytics in the dashboard, refer to [Analytics](https://developers.cloudflare.com/analytics/).

## How it works

Analytics collects data based on the time-to-first-byte (TTFB) from your origin to the Cloudflare network. TTFB is the delay between when Cloudflare sends a request to your server and when it receives the first byte in response. Argo Smart Routing optimizes your server's network transit time to minimize this delay.

Note

Detailed performance data within **Origin Performance (Argo)** will only display if Argo has routed at least 500 origin requests within the last 48 hours.

## Types of analytics

The dashboard displays two different views for performance data:

* **Origin Response Time**: A histogram shows response time from your origin to the Cloudflare network. The blue bars show time-to-first-byte (TTFB) without Argo, while the orange bars show TTFB where Argo found a Smart Route.
* **Geography**: A map shows the improvement in response time at each Cloudflare data center.  
   * A negative value indicates that requests from that location would not have benefited from Argo Smart Routing, so instead would have been routed directly.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/argo-smart-routing/","name":"Argo Smart Routing"}},{"@type":"ListItem","position":3,"item":{"@id":"/argo-smart-routing/analytics/","name":"Analytics"}}]}
```

---

---
title: Argo for Packets
description: Optimize IP layer routing for Magic Transit, Cloudflare WAN, and Cloudflare for Offices.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Argo for Packets

Argo for Packets optimizes IP layer network routing for Cloudflare network services products, including [Magic Transit](https://developers.cloudflare.com/magic-transit/), [Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/) (formerly Magic WAN), and [Cloudflare for Offices ↗](https://blog.cloudflare.com/cloudflare-for-offices/).

Argo for Packets monitors the performance of network paths between every Cloudflare data center and your origin. It uses existing Layer 4 traffic data and network analytics to select the fastest, most available path.

Organizations with multiple origin locations benefit most from Argo for Packets, because it optimizes complex Internet paths that would otherwise route suboptimally.

To begin using Argo for Packets, contact your account manager.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/argo-smart-routing/","name":"Argo Smart Routing"}},{"@type":"ListItem","position":3,"item":{"@id":"/argo-smart-routing/argo-for-packets/","name":"Argo for Packets"}}]}
```

---

---
title: Automatic Platform Optimization
description: Cache and serve your entire WordPress site from the Cloudflare edge network.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Automatic Platform Optimization

Take your WordPress site’s performance to the next level with Automatic Platform Optimizations (APO). APO allows Cloudflare to serve your entire WordPress site from its edge network ensuring consistent, fast performance for visitors no matter where they are.

Automatic Platform Optimization is the result of using the power of [Cloudflare Workers](https://developers.cloudflare.com/workers/) to intelligently cache dynamic content. By caching dynamic content, Cloudflare can serve the entire website from our edge network to make a site's time to first byte (TTFB) both fast and consistent.

To read more about the benefits of using APO with your site, see [The Benefits of Automatic Platform Optimization blog ↗](https://blog.cloudflare.com/automatic-platform-optimizations-starting-with-wordpress/#the-benefits-of-automatic-platform-optimization). You must use the Cloudflare for WordPress plugin to begin using APO.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/automatic-platform-optimization/","name":"Automatic Platform Optimization"}}]}
```

---

---
title: About
description: How APO caches dynamic WordPress content at the Cloudflare edge.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# About

With Automatic Platform Optimization (APO), Cloudflare serves your entire site from our edge network, ensuring customers see improved performance when visiting your site. Cloudflare typically only caches static content, but with APO, we can also cache dynamic content — like HTML — to serve the entire site from the cache. This process removes round trips from the origin to drastically improve time to first byte (TTFB) along with other site performance metrics. In addition to caching dynamic content, APO caches third-party scripts to further reduce the number of requests that leave Cloudflare's edge network.

With APO, you can manage your WordPress site as normal. Whenever you update content in WordPress, Cloudflare updates content on our edge to prevent serving stale content when you use Cloudflare's WordPress plugin. Additionally, for logged-in or administrator users, we bypass the cache to ensure that private content is not cached and served to other visitors. Find more about [what APO can do for you. ↗](https://www.youtube.com/watch?v=DWANhxoDxFI?feature=youtu.be)

## Limitations

Automatic Platform Optimization is not compatible with Enterprise [subdomain setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/) when a subdomain, for example, `www` is in a different zone to the apex domain.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/automatic-platform-optimization/","name":"Automatic Platform Optimization"}},{"@type":"ListItem","position":3,"item":{"@id":"/automatic-platform-optimization/about/","name":"About"}}]}
```

---

---
title: Plugin compatibility
description: WordPress plugins supported and known to conflict with APO.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Plugin compatibility

Currently, WordPress offers over 50,000 plugins for download. As a result, testing the compatibility between APO and every available plugin is impossible. However, Cloudflare has a list of officially supported plugins and a list of plugins known to cause issues when APO is enabled.

For questions about a specific plugin not shown in the list, create a thread in the [Cloudflare Community ↗](https://community.cloudflare.com/) to begin the conversation.

Note

The Cloudflare APO WordPress plugin does not support multisite WordPress installation.

## Compatible plugins

* [NitroPack ↗](https://nitropack.io/)
* [FlyingPress ↗](https://flyingpress.com/)
* [WP Rocket ↗](https://community.cloudflare.com/t/cloudflares-apo-with-wp-rockets-minified-css/225906/3?u=yevgen) **version 3.8.6 or later**
* [BigCommerce ↗](https://wordpress.org/plugins/bigcommerce/)
* [Easy Digital Downloads ↗](https://wordpress.org/plugins/easy-digital-downloads/)
* [WooCommerce ↗](https://wordpress.org/plugins/woocommerce/)
* [Redis Object Cache ↗](https://wordpress.org/plugins/redis-cache/)
* [Object Cache Pro ↗](https://objectcache.pro)
* [YITH WooCommerce Wishlist ↗](https://wordpress.org/plugins/yith-woocommerce-wishlist/)
* [WP EasyCart ↗](https://wordpress.org/plugins/wp-easycart/)
* [Ecwid Ecommerce Shopping Cart ↗](https://wordpress.org/plugins/ecwid-shopping-cart/)
* [WP ECommerce ↗](https://wordpress.org/plugins/wp-e-commerce/)
* [Bookly ↗](https://wordpress.org/plugins/bookly-responsive-appointment-booking-tool/)
* [WPTouch ↗](https://wordpress.org/plugins/wptouch/)
* [Mobile Detect ↗](https://wordpress.org/plugins/tinywp-mobile-detect/)
* [WordPress Mobile Pack ↗](https://wordpress.org/plugins/wordpress-mobile-pack/)
* [WP-Mobilizer ↗](https://wordpress.org/plugins/wp-mobilizer/)
* [Any Mobile Theme Switcher ↗](https://wordpress.org/plugins/any-mobile-theme-switcher/)
* [Easy Social Share Buttons ↗](https://codecanyon.net/item/easy-social-share-buttons-for-wordpress/6394476)
* [Jetpack (Mobile Theme) ↗](https://wordpress.org/plugins/jetpack/)
* [WPML ↗](https://wpml.org/)
* [Hummingbird ↗](https://wordpress.org/plugins/hummingbird-performance/)
* [Imunify360 ↗](https://docs.imunify360.com/features/#webshield)
* [Perfmatters ↗](https://perfmatters.io/docs/cloudflare-wordpress-settings/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/automatic-platform-optimization/","name":"Automatic Platform Optimization"}},{"@type":"ListItem","position":3,"item":{"@id":"/automatic-platform-optimization/about/","name":"About"}},{"@type":"ListItem","position":4,"item":{"@id":"/automatic-platform-optimization/about/plugin-compatibility/","name":"Plugin compatibility"}}]}
```

---

---
title: Test current speed
description: Benchmark your site speed before enabling APO with GTmetrix.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Test current speed

Before you begin using APO, we recommend testing your current site speed. Your site speed results give your website a letter grade and performance rating.

1. Visit [GTmetrix ↗](https://gtmetrix.com/).
2. In the text field, enter your website's URL.
3. Click **Test your site**.

After the test runs, you can view your site's grade, performance rating, and other performance metrics.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/automatic-platform-optimization/","name":"Automatic Platform Optimization"}},{"@type":"ListItem","position":3,"item":{"@id":"/automatic-platform-optimization/about/","name":"About"}},{"@type":"ListItem","position":4,"item":{"@id":"/automatic-platform-optimization/about/test-current-speed/","name":"Test current speed"}}]}
```

---

---
title: Troubleshooting
description: Resolve common APO issues including plugin detection and stale content.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

## WordPress plugin is undetected on Cloudflare dashboard

The WordPress plugin may go undetected on your Cloudflare dashboard for a few reasons.

* Versions older than 3.8.2 of the WordPress plugin are installed.  
   * **Solution:** Install version 4.4.0 of the WordPress plugin.
* Version 3.8.2 of the plugin is installed but existing cache plugins return stale responses, for example, without `cf-edge-cache` header.  
   * **Solution:** Enable APO from the WordPress plugin and purge the cache in the existing cache plugins.
* WordPress only runs on a subdomain, but WordPress and the WordPress plugin check against the apex domain.  
   * **Solution:** For additional information, see [Subdomains and subdirectories](https://developers.cloudflare.com/automatic-platform-optimization/reference/subdomain-subdirectories/)

If your Cloudflare dashboard cannot detect the WordPress plugin after trying the solutions above, ensure you completed all of the steps listed in [Activate the Cloudflare WordPress plugin](https://developers.cloudflare.com/automatic-platform-optimization/get-started/activate-cf-wp-plugin/).

Note

The Cloudflare APO WordPress plugin does not support multisite WordPress installation.

## WordPress returns stale content

If WordPress is returning stale content, [purge the cache](https://developers.cloudflare.com/cache/how-to/purge-cache/) when APO is enabled.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/automatic-platform-optimization/","name":"Automatic Platform Optimization"}},{"@type":"ListItem","position":3,"item":{"@id":"/automatic-platform-optimization/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: FAQs
description: Answers to common questions about APO caching, Page Rules, and WordPress integration.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# FAQs

## Do I still need to create "Edge Cache TTL" page rules with "Cache Level: Cache Everything"?

No, you do not need create Edge Cache TTL page rules. When the WordPress plugin is installed, APO automatically caches content for 30 days and invalidates on change within 30 seconds. However, because APO now supports cache-related page rules, make sure existing page rules do not affect the resources served by APO.

## Does Origin Cache Control override APO?

No. APO ignores Origin Cache Control for caching on the Edge, but APO serves original Origin Cache Control to the client.

## Why are my browser cache control headers missing with APO?

The browser cache control headers may be missing with APO if you set your **Browser Cache TTL** to **Respect Existing Headers**. For example:

Terminal window

```

curl --silent --verbose --output /dev/null https://example.com/ --header 'Accept: text/html' 2>&1 | grep cache-control


```

```

< cache-control: max-age=86400, stale-while-revalidate=86400, stale-if-error=86400


```

## Is the stale-if-error directive still needed with APO?

No, the `stale-if-error` directive is not needed because the feature is built into APO.

## When I check the posts and homepage cache status, the response header shows `cf-cache-status: BYPASS`. Is APO working?

When Chrome DevTools is open, Chrome sends `Cache-Control: no-cache` by default. You can uncheck the **Disable cache (while DevTools is open)** setting and see that `cf-cache-status: HIT` and `cf-apo-via: cache` headers will be returned.

## When I check `cf-cache-status` via cURL, `MISS` and `DYNAMIC` are always returned. In my browser, I see `HIT` but other tools return `DYNAMIC`. Is this expected behavior?

Yes, this is expected behavior because the requests must contain `accept: "text/html"`.

## Are Google Fonts optimized when APO is activated?

Yes, Google Fonts are also optimized when APO is activated. You can confirm the optimization by checking the font URLs. For example, the URL will change from `https://fonts.gstatic.com/s/...` to `https://example.com/fonts.gstatic.com/s/...` when the site loads. For proxied fonts, the `cf-apo-via:proxy` header is returned.

## Can I customize query string caching with APO?

For more information on query parameters, see [Query parameters and cached responses](https://developers.cloudflare.com/automatic-platform-optimization/reference/query-parameters/).

## Why are my font URLs not being transformed?

APO will skip URL font transformation when the `content-security-policy` response header is present but missing the values described below.

To fix the problem, the `content-security-policy` header value must allow for `unsafe-inline` on either the `style-src` or `default-src` directive. For example, `Content-Security-Policy: style-src unsafe-inline;`.

The header must allow for `self` on either the `font-src` or `default-src` directive. For example, `Content-Security-Policy: font-src self;`.

## Why do I see Worker subrequests in my zone logs when using APO?

APO uses Cloudflare Workers internally to optimize content delivery, which results in Worker subrequests. These subrequests may appear in your zone logs (for example, via Logpush).

## For the APO plugin why do I see: This plugin hasn’t been tested with the latest 3 major releases of WordPress. It may no longer be maintained or supported and may have compatibility issues when used with more recent versions of WordPress.

It is not uncommon for mature plugins to see no updates for longer periods than it takes to trigger the WordPress not tested warning. The warning is for notification purposes and is not an indication that a plugin no longer works. It is still maintained.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/automatic-platform-optimization/","name":"Automatic Platform Optimization"}},{"@type":"ListItem","position":3,"item":{"@id":"/automatic-platform-optimization/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/automatic-platform-optimization/troubleshooting/faq/","name":"FAQs"}}]}
```

---

---
title: Activate the Cloudflare WordPress plugin
description: The easiest way to begin using APO is directly from Cloudflare's WordPress plugin. Before you can use APO, you must first install and activate the plugin and then activate APO.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Activate the Cloudflare WordPress plugin

After you [change your nameservers](https://developers.cloudflare.com/automatic-platform-optimization/get-started/change-nameservers/), activate the Cloudflare WordPress plugin.

## Prerequisites

Before activating the Cloudflare WordPress plugin, review the following prerequisites.

### Plan type

For users on the free plan, [purchase APO](#purchase-apo) before installing the WordPress plugin.

For users on a Pro plan or higher, continue to [Install and activate](#install-and-activate-the-cloudflare-wordpress-plugin) the Cloudflare WordPress plugin.

### Plugin compatibility

Cloudflare recommends turning off plugins such as WP Rocket Cache Plugin, W3 Total Cache, or similar plugins when first setting up APO. After confirming APO is working, we recommend testing whether turning on the plugins listed above improves results or causes unexpected behavior. In many cases, using APO along with other caching plugins can cause unexpected results.

We also recommend clearing the server cache for the WP Rocket Cache plugin, W3 Total Cache, or similar plugins after APO activation.

For more details, refer to [Plugin compatibility](https://developers.cloudflare.com/automatic-platform-optimization/about/plugin-compatibility/).

### Limitations

The Cloudflare APO WordPress plugin does not support multisite WordPress installation.

## Purchase APO

1. In the Cloudflare dashboard, go to the **Speed** \> **Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/speed/optimization)
2. Go to **Content Optimization**.
3. For **Automatic Platform Optimization for WordPress**, select **Purchase**.
4. Enter your payment information and select **Confirm payment**.

## Install and activate the Cloudflare WordPress plugin

The easiest way to begin using APO is directly from Cloudflare’s WordPress plugin. Before you can use APO, you must first install and activate the plugin and then activate APO.

1. Navigate and log in to your WordPress account.
2. Select **Plugins** \> **Add new**.
3. In the search field, enter `Cloudflare`.
4. Locate the Cloudflare plugin and select **Install now**.
5. After the plugin finishes installing, select **Activate**. The Cloudflare plugin now displays in your Plugins list.

## Activate APO

To create the connection between WordPress and Cloudflare, you will create an API token from your Cloudflare dashboard and add it to WordPress. To set up APO on a subdomain, refer to [Subdomains and subdirectories](https://developers.cloudflare.com/automatic-platform-optimization/reference/subdomain-subdirectories/).

## Create the API token from Cloudflare

1. In the Cloudflare dashboard, go to the **Account API tokens** page.  
[ Go to **Account API tokens** ](https://dash.cloudflare.com/?to=/:account/api-tokens)
2. Select **Create Token**.
3. Locate **WordPress** from the list and select **Use template**.
4. Select **Continue to summary** at the bottom of the page.
5. On the **WordPress API token summary** page, select **Create Token**. Your API token displays.
6. Select the **Copy** button to copy your token. You will need to paste the token in the next section.

Note

Copy and paste your API token into a document saved on your computer to easily reference it again.

## Add your API token to WordPress

1. Open your WordPress account and navigate to Plugins.
2. Locate the Cloudflare plugin and select **Settings**.
3. Select the option to sign in with an existing account.
4. Enter your email address and paste the token you copied in Step 7 of Create the API token from Cloudflare.
5. Select **Save API Credentials**.
6. For **Apply Recommended Cloudflare Settings for WordPress**, select **Apply**.
7. For **Automatic Platform Optimization**, switch the toggle to **On** to enable APO.

To verify APO is working, see [Verify APO works](https://developers.cloudflare.com/automatic-platform-optimization/get-started/verify-apo-works/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/automatic-platform-optimization/","name":"Automatic Platform Optimization"}},{"@type":"ListItem","position":3,"item":{"@id":"/automatic-platform-optimization/get-started/","name":"Get started"}},{"@type":"ListItem","position":4,"item":{"@id":"/automatic-platform-optimization/get-started/activate-cf-wp-plugin/","name":"Activate the Cloudflare WordPress plugin"}}]}
```

---

---
title: Change nameservers
description: Update your domain nameservers to Cloudflare for APO to work.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Change nameservers

After you [confirm your DNS records](https://developers.cloudflare.com/automatic-platform-optimization/get-started/confirm-dns-records/), change your nameservers.

Updating your domain to use Cloudflare's nameservers is a critical step to ensure Cloudflare can optimize and protect your site. Nameservers are your primary DNS controller and identify the location of your domain on the Internet.

Domain registrars can take up to 24 hours to process the nameserver updates. You will receive an email from Cloudflare once your site is activated.

## Lookup domain name registration

1. Visit [WHOIS ↗](https://lookup.icann.org/) to look up your domain name registration.
2. In the text field, enter your domain name without `https://www.` and select **Lookup**.
3. From **Domain Information**, make note of the nameserver information that displays. You will update those nameservers to point to Cloudflare.

We recommend keeping this browser tab or window open and opening a new tab or window for the next section.

## Update your nameserver with your domain registrar

1. Log in to the administrator account for your domain registrar.
2. Navigate to DNS Management.
3. Locate your nameserver information. Your nameservers should match the information from Step 3 of Lookup domain name registration.
4. Replace the existing nameserver information with the Cloudflare nameservers from Step 4 of Create the custom nameserver with Cloudflare.

Note

You may be prompted to confirm the nameserver change with your domain registrar. Confirm or continue after making the update.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/automatic-platform-optimization/","name":"Automatic Platform Optimization"}},{"@type":"ListItem","position":3,"item":{"@id":"/automatic-platform-optimization/get-started/","name":"Get started"}},{"@type":"ListItem","position":4,"item":{"@id":"/automatic-platform-optimization/get-started/change-nameservers/","name":"Change nameservers"}}]}
```

---

---
title: Confirm DNS records
description: Verify your DNS records are correct before enabling APO.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Confirm DNS records

Before you change your nameservers, confirm your DNS records are displaying correctly.

1. In the Cloudflare dashboard, go to the DNS **Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. To add a record, select **Add record**.
3. To edit an existing record, select **Edit** for the appropriate record.
4. After making your changes, select **Save**.

After you confirm your DNS records, [change your nameservers](https://developers.cloudflare.com/automatic-platform-optimization/get-started/change-nameservers/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/automatic-platform-optimization/","name":"Automatic Platform Optimization"}},{"@type":"ListItem","position":3,"item":{"@id":"/automatic-platform-optimization/get-started/","name":"Get started"}},{"@type":"ListItem","position":4,"item":{"@id":"/automatic-platform-optimization/get-started/confirm-dns-records/","name":"Confirm DNS records"}}]}
```

---

---
title: Verify APO works
description: When APO is working, three headers are present:  CF-Cache-Status, cf-apo-via,cf-edge-cache. APO works correctly when the headers exactly match the headers below.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Verify APO works

You can check whether or not APO is working by verifying APO headers are present. When APO is working, three headers are present: `CF-Cache-Status`, `cf-apo-via`, `cf-edge-cache`.

1. Visit [Uptrends.com ↗](https://www.uptrends.com/tools/http-response-header-check).
2. In the text field, enter the URL for your WordPress homepage including the `https://www.`.
3. Select **Start test**. The **Response Headers** table displays.
4. Locate the three header responses and their description. APO is working correctly when the headers exactly match the headers below.
* `CF-Cache-Status` | `HIT`  
   * The `cf-cache-status` header displays if the asset is served from the cache or was considered dynamic and served from the origin.
* `cf-apo-via` | `tcache`  
   * The `cf-apo-via` header returns the APO status for the given request.
* `cf-edge-cache` | `cache, platform=wordpress`  
   * The `cf-edge-cache` headers confirms the WordPress plugin is installed and enabled.

In a terminal, use the following cURL. The header `'accept: text/html'` is important.

Terminal window

```

curl -svo /dev/null -A "CF" 'https://example.com/' -H 'accept: text/html' 2>&1 | grep 'cf-cache-status\|cf-edge\|cf-apo-via'


```

```

< cf-cache-status: HIT

< cf-apo-via: cache

< cf-edge-cache: cache,platform=wordpress


```

As always, `cf-cache-status` displays if the asset hit the cache or was considered dynamic and served from the origin.

* `cf-apo-via` | `tcache`  
   * The `cf-apo-via` header returns the APO status for the given request.
* `cf-edge-cache` | `cache, platform=wordpress`  
   * The `cf-edge-cache` headers confirms the WordPress plugin is installed and enabled.

## Verify the APO integration and WordPress integration work

Open your WordPress site and publish a change. When the integration is working, the page is cached with `cf-cache-status: HIT` and `cf-apo-via: tcache`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/automatic-platform-optimization/","name":"Automatic Platform Optimization"}},{"@type":"ListItem","position":3,"item":{"@id":"/automatic-platform-optimization/get-started/","name":"Get started"}},{"@type":"ListItem","position":4,"item":{"@id":"/automatic-platform-optimization/get-started/verify-apo-works/","name":"Verify APO works"}}]}
```

---

---
title: Cache by device type
description: Serve different cached content to mobile, tablet, and desktop visitors.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache by device type

APO cache by device type provides all of the same benefits of Cloudflare's cache while targeting visitors with content appropriate to their device. Cloudflare evaluates the `User-Agent` header in the HTTP request to identify the device type. Cloudflare then identifies each device type with a case insensitive match to the regex below:

* **Mobile**: `(?:phone|windows\s+phone|ipod|blackberry|(?:android|bb\d+|meego|silk|googlebot) .+? mobile|palm|windows\s+ce|opera mini|avantgo|mobilesafari|docomo|kaios)`
* **Tablet**: `(?:ipad|playbook|(?:android|bb\d+|meego|silk)(?! .+? mobile))`
* **Desktop**: Everything else not matched above.

To enable caching by device type, enable the setting from the Cloudflare dashboard's APO card or from the WordPress plugin version 4.4.0 or later.

Once enabled, Cloudflare sends a `CF-Device-Type` HTTP header to your origin with a value of either `mobile`, `tablet`, `desktop` for every request to specify the visitor’s device type. If your origin responds with the appropriate content for that device type, Cloudflare only caches the resource for that specific device type.

Note

Changing Cache By Device Type setting will invalidate Cache.

The Cloudflare for WordPress plugin automatically purges all cache variations for updated pages.

Cloudflare recommends that you use plugins that support cache by device type, which you may have to enable on the plugin. You will still need to test your plugins to make sure they behave as expected.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/automatic-platform-optimization/","name":"Automatic Platform Optimization"}},{"@type":"ListItem","position":3,"item":{"@id":"/automatic-platform-optimization/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/automatic-platform-optimization/reference/cache-device-type/","name":"Cache by device type"}}]}
```

---

---
title: Page Rule integration with APO
description: Page Rules that control APO caching behavior for specific URL patterns.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Page Rule integration with APO

The following Page Rules can control APO. Any changes to caching via Page Rules require purging the cache for the changes to take effect.

Warning

Consider using [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/) instead to control APO due to their enhanced configurability.

* **Cache Level: Bypass** — APO bypasses pages with response header `cf-apo-via: origin,page-rules`
* **Cache Level: Ignore Query String** — APO ignores all query strings when serving from Cache.
* **Cache Level: Cache Everything** — APO caches pages with all query strings.  
Warning  
Automatic page purge via the WordPress plugin won’t clean all cached pages, only pages without query strings. Cached responses will be returned even with request header `cache-control: no-cache`.
* **Bypass Cache on Cookie (Business and Enterprise plans only)** — APO applies custom bypass cookies in addition to the default list.
* **Edge Cache TTL** — APO applies custom Edge TTL instead of 30 days. This page rule is helpful for pages that can generate CAPTCHAs or nonces.
* **Browser Cache TTL** — APO applies custom Browser TTL.
* `CDN-Cache-Control` and `Cloudflare-CDN-Cache-Control` – Enables users to have detailed control over cache TTLs without using a page rule. For more information on the `CDN-Cache-Control` and `Cloudflare-CDN-Cache-Control` headers, refer to [CDN-Cache-Control](https://developers.cloudflare.com/cache/concepts/cache-control/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/automatic-platform-optimization/","name":"Automatic Platform Optimization"}},{"@type":"ListItem","position":3,"item":{"@id":"/automatic-platform-optimization/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/automatic-platform-optimization/reference/page-rule-integration/","name":"Page Rule integration with APO"}}]}
```

---

---
title: Query parameters and cached responses
description: How APO handles query parameters, UTMs, and cookies in cached responses.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Query parameters and cached responses

Query parameters often signal the presence of dynamic content. As a result, if there are query parameters in the URL, APO bypasses the cache and attempts to get a new version of the page from the origin by default. Because query parameters are also often used for marketing attribution, like UTMs, quick loading times are especially important for users.

To add a query parameter to our allowlist, [create a post in the community ↗](https://community.cloudflare.com/) for consideration.

APO serves cached content as long as the query parameters in the URL are one of the following:

* `ref`
* `utm_source`
* `utm_medium`
* `utm_campaign`
* `utm_term`
* `utm_content`
* `utm_expid`
* `fbclid`
* `fb_action_ids`
* `fb_action_types`
* `fb_source`
* `mc_cid`
* `mc_eid`
* `gclid`
* `dclid`
* `_ga`
* `campaignid`
* `adgroupid`
* `_ke`
* `cn-reloaded`
* `age-verified`
* `ao_noptimize`
* `usqp`
* `mkt_tok`
* `epik`
* `ck_subscriber_id`

## Cookies prefixes that always bypass cache

* `wp-`
* `wordpress`
* `comment_`
* `woocommerce_`
* `xf_`
* `edd_`
* `jetpack`
* `yith_wcwl_session_`
* `yith_wrvp_`
* `wpsc_`
* `ecwid`
* `ec_`
* `bookly_`
* `bookly`

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/automatic-platform-optimization/","name":"Automatic Platform Optimization"}},{"@type":"ListItem","position":3,"item":{"@id":"/automatic-platform-optimization/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/automatic-platform-optimization/reference/query-parameters/","name":"Query parameters and cached responses"}}]}
```

---

---
title: Subdomains and subdirectories
description: Run APO on WordPress subdomains and subdirectory installations.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Subdomains and subdirectories

## Run APO on a subdomain

After you enable APO, you configure it to run on the subdomain that uses WordPress. For example, if you have a website called `www.mysite.com` which includes a subdomain running WordPress called `shop.mysite.com`, you would configure APO to run on the `shop.mysite.com` subdomain.

1. Install version 4.4.0 or later of the Cloudflare WordPress plugin.
2. Log in using Cloudflare **API token** or **Global key**.
3. Enable APO. The subdomain displays in the list of hostnames in the card.
4. Repeat the process for each subdomain to enable APO.

By default, APO runs on the apex domain (also known as "root domain" or "naked domain"). If you choose to run APO on a subdomain, the apex domain is automatically disabled. To run APO on a subdomain and the apex domain, upgrade the WordPress plugin to version 4.4.0 or later on the apex domain and re-enable APO.

## Run APO on a subdirectory

After you enable APO, you configure it to run on the subdirectory that uses WordPress. For example, if you have a website called `www.mysite.com` which includes a subdirectory running WordPress called `mysite.com/shop`, you would configure APO to run on the `mysite.com` domain.

1. Install the Cloudflare WordPress plugin.
2. Add your Cloudflare API Token.
3. Activate APO.

Repeat steps 1 and 2 for each subdirectory to activate the WordPress plugin for automatic cache purging.

## Run APO only on a subdirectory

If you choose to run APO only on a subdirectory, the rest of the domain should be configured to bypass APO. You can bypass APO in one of two ways.

### Use the `cf-edge-cache` response header

The `cf-edge-cache: no-cache` instructs the APO service to bypass caching for non-WordPress parts of the site. You can implement this option with Cloudflare Workers using the example below.

JavaScript

```

export default {

  async fetch(request, env, ctx) {

    const originalResponse = await fetch(request);


    // Response properties are immutable. To change them, construct a new Response object.

    const response = new Response(originalResponse.body, originalResponse);


    // Response headers can be modified through the headers `set` method.

    response.headers.set("cf-edge-cache", "no-cache");


    return response;

  },

};


```

### Use Cache Rules

Create a [cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/) to exclude non-WordPress portions of the site from caching using **Cache eligibility: Bypass cache**. This option disables all caching, including static assets for those paths. As a result, we recommend disabling APO via the response header.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/automatic-platform-optimization/","name":"Automatic Platform Optimization"}},{"@type":"ListItem","position":3,"item":{"@id":"/automatic-platform-optimization/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/automatic-platform-optimization/reference/subdomain-subdirectories/","name":"Subdomains and subdirectories"}}]}
```

---

---
title: Cloudflare Cache
description: Cache and serve static and dynamic content from Cloudflare edge servers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare Cache

Cache content across Cloudflare's global server network.

 Available on all plans 

Cache stores copies of frequently accessed content (such as images, videos, or webpages) in geographically distributed data centers that are located closer to end users than origin servers, reducing server load and improving website performance.

## Features

###  Default cache behavior 

Learn about default cache behavior, default cached file extensions and cache responses.

[ Use Default cache behavior ](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/) 

###  Cache Rules 

Configure Cache Rules to optimize your website by specifying which resources should be cached and for how long.

[ Use Cache Rules ](https://developers.cloudflare.com/cache/how-to/cache-rules/) 

###  Tiered Cache 

Enable Tiered Cache to optimize content delivery by caching frequently accessed content in multiple locations for faster delivery and reduced origin traffic.

[ Use Tiered Cache ](https://developers.cloudflare.com/cache/how-to/tiered-cache/) 

###  Cache Reserve 

Use Cloudflare's persistent storage to increase cache times.

[ Use Cache Reserve ](https://developers.cloudflare.com/cache/advanced-configuration/cache-reserve/) 

###  Purge 

Instantly purge cached files to force Cloudflare to fetch fresh versions from your web server files. You can purge specific files or all at once.

[ Use Purge ](https://developers.cloudflare.com/cache/how-to/purge-cache/) 

---

## Related products

**[Load Balancing](https://developers.cloudflare.com/load-balancing/)** 

Cloudflare Load Balancing distributes traffic across your endpoints, reducing endpoint strain and latency and improving the end users experience.

**[Images](https://developers.cloudflare.com/images/)** 

A suite of products tailored to your image-processing needs.

**[Workers](https://developers.cloudflare.com/workers/)** 

Cloudflare Workers allows developers to build serverless applications and deploy instantly across the globe for exceptional performance, reliability, and scale.

**[Rules](https://developers.cloudflare.com/rules/)** 

Cloudflare Rules allows you to make adjustments to requests and responses, configure Cloudflare settings, and trigger specific actions for matching requests.

**[Cloudflare Network Interconnect](https://developers.cloudflare.com/network-interconnect/)** 

Cloudflare Network Interconnect (CNI) allows you to connect your network infrastructure directly with Cloudflare – rather than using the public Internet – for a more reliable and secure experience.

**[R2](https://developers.cloudflare.com/r2/)** 

Cloudflare R2 Storage allows developers to store large amounts of unstructured data without the costly egress bandwidth fees associated with typical cloud storage services.

**[Dedicated CDN Egress IPs](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/)** 

Smart Shield Advanced provides dedicated egress IPs (from Cloudflare to your origin) for your layer 7 WAF and CDN services, as well as Spectrum.

---

## More resources

[Plans](https://www.cloudflare.com/cdn/) 

Compare available Cloudflare plans

[Pricing](https://www.cloudflare.com/plans/#overview) 

Explore pricing options for Cache

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}}]}
```

---

---
title: Plans
description: Compare cache features available on each Cloudflare plan.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Plans

Cloudflare provides the following features for different [plans ↗](https://www.cloudflare.com/plans/).

## Features

### Always Online

**Link:**[Always Online](https://developers.cloudflare.com/cache/how-to/always-online/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Crawl interval**

Available on all plans

* **Free:** Every 30 days
* **Pro:** Every 15 days
* **Business:** Every 5 days
* **Enterprise:** Every 5 days

### Browser Cache TTL

**Link:**[Browser Cache TTL](https://developers.cloudflare.com/cache/how-to/edge-browser-cache-ttl/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Minimum Browser Cache TTL (Page Rules)**
* **Free:** 2 minutes
* **Pro:** 2 minutes
* **Business:** 2 minutes
* **Enterprise:** 30 seconds

**Minimum Browser Cache TTL**
* **Free:** 1 second
* **Pro:** 1 second
* **Business:** 1 second
* **Enterprise:** 1 second

**Default Browser Cache TTL**
* **Free:** 4 hours
* **Pro:** 4 hours
* **Business:** 4 hours
* **Enterprise:** 4 hours

### Cache analytics

**Link:**[Cache analytics](https://developers.cloudflare.com/cache/performance-review/cache-analytics/)

**Feature availability**
* **Free:** No
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Retention period**
* **Free:** N/A
* **Pro:** 7 days
* **Business:** 30 days
* **Enterprise:** 30 days

### Cache keys

**Link:**[Cache keys](https://developers.cloudflare.com/cache/how-to/cache-keys/)

**Cache deception armor**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Cache by device type**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Ignore query string**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Sort query string**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Query string**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

**Headers**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

**Cookie**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

**Host**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

**User features**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

### Set caching level

**Link:**[Set caching level](https://developers.cloudflare.com/cache/how-to/set-caching-levels/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### Cache reserve

**Link:**[Cache reserve](https://developers.cloudflare.com/cache/advanced-configuration/cache-reserve/)

**Feature availability**
* **Free:** Paid add-on
* **Pro:** Paid add-on
* **Business:** Paid add-on
* **Enterprise:** Paid add-on

### Cache Rules

**Link:**[Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Number of rules**
* **Free:** 10
* **Pro:** 25
* **Business:** 50
* **Enterprise:** 300

### Cache by status code

**Link:**[Cache by status code](https://developers.cloudflare.com/cache/how-to/configure-cache-status-code/)

**Feature availability**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

### Crawler Hints

**Link:**[Crawler Hints](https://developers.cloudflare.com/cache/advanced-configuration/crawler-hints/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### CSAM Scanning Tool

**Link:**[CSAM Scanning Tool](https://developers.cloudflare.com/cache/reference/csam-scanning/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### Development mode

**Link:**[Development mode](https://developers.cloudflare.com/cache/reference/development-mode/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### Edge Cache TTL

**Link:**[Edge Cache TTL](https://developers.cloudflare.com/cache/how-to/edge-browser-cache-ttl/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Minimum Edge Cache TTL**
* **Free:** 2 hours
* **Pro:** 1 hour
* **Business:** 1 second
* **Enterprise:** 1 second

### ETag Headers

**Link:**[ETag Headers](https://developers.cloudflare.com/cache/reference/etag-headers/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### Purge cache

**Link:**[Purge cache](https://developers.cloudflare.com/cache/how-to/purge-cache/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Purge options**
* **Free:** URL, Hostname, Tag, Prefix, and Purge Everything
* **Pro:** URL, Hostname, Tag, Prefix, and Purge Everything
* **Business:** URL, Hostname, Tag, Prefix, and Purge Everything
* **Enterprise:** URL, Hostname, Tag, Prefix, and Purge Everything

### Purge limits for hostname, tag, prefix URL, and purge everything.

**Link:**[Purge limits for hostname, tag, prefix URL, and purge everything.](https://developers.cloudflare.com/cache/how-to/purge-cache/)

**Requests**

Available on all plans

* **Free:** 5 requests per minute
* **Pro:** 5 requests per second
* **Business:** 10 requests per second
* **Enterprise:** 50 requests per second

**Bucket size**
* **Free:** 25
* **Pro:** 25
* **Business:** 50
* **Enterprise:** 500

**Max operations per request**
* **Free:** 100
* **Pro:** 100
* **Business:** 100
* **Enterprise:** 100

### Single file purge

**Link:**[Single file purge](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-single-file/)

**URLs**

Available on all plans

* **Free:** 800 URLs per second
* **Pro:** 1500 URLs per second
* **Business:** 1500 URLs per second
* **Enterprise:** 3000 URLs per second

**Max operations per request**
* **Free:** 100
* **Pro:** 100
* **Business:** 100
* **Enterprise:** 500

### Query string sort

**Link:**[Query string sort](https://developers.cloudflare.com/cache/advanced-configuration/query-string-sort/)

**Feature availability**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

### Tiered cache

**Link:**[Tiered cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/)

**Tiered Cache**

Available on all plans

* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Smart Topology**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Generic Global Topology**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

**Regional Tiered Cache**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

**Custom Topology**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

### Vary for images

**Link:**[Vary for images](https://developers.cloudflare.com/cache/advanced-configuration/vary-for-images/)

**Feature availability**
* **Free:** No
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/plans/","name":"Plans"}}]}
```

---

---
title: Get started
description: Set up and configure Cloudflare caching for your website.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

Cloudflare speeds up your website by caching content across globally distributed data centers.

Content can be static or dynamic. Static content — such as images, CSS, and JavaScript files — is [cacheable](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#default-cached-file-extensions) by default. Dynamic content, such as HTML pages, is not cached by default, but you can use [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/) to cache it.

Cloudflare caches static content based on the following factors:

* [Caching levels](https://developers.cloudflare.com/cache/how-to/set-caching-levels/)
* [File extension](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#default-cached-file-extensions)
* Presence of [query strings](https://developers.cloudflare.com/cache/advanced-configuration/query-string-sort/)
* [Origin cache-control headers](https://developers.cloudflare.com/cache/concepts/cache-control/)
* Origin headers that indicate dynamic content
* Cache rules that bypass cache on cookie

Cloudflare only caches resources within the Cloudflare data center that serve the request. Cloudflare does not cache off-site or third-party resources, or content hosted on [DNS-only (unproxied)](https://developers.cloudflare.com/dns/proxy-status/) DNS records.

## Learn the basics

Discover the benefits of caching with Cloudflare's CDN and understand the default cache behavior.

* [Understand what is a CDN ↗](https://www.cloudflare.com/learning/cdn/what-is-a-cdn/)
* [Understand default cache behavior](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/)
* [Understand the default file types Cloudflare caches](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#default-cached-file-extensions)

## Make more resources cacheable

Configure your settings to cache static HTML or cache anonymous page views of dynamic content.

* [Customize Caching with Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/)
* [Specify which resources to cache](https://developers.cloudflare.com/cache/concepts/customize-cache/)
* [Understand Origin Cache Control](https://developers.cloudflare.com/cache/concepts/cache-control/)
* [Cache by device type (Enterprise only)](https://developers.cloudflare.com/cache/how-to/cache-rules/examples/cache-device-type/)

## Improve cache HIT rates

Include or exclude query strings, optimize cache keys, or enable [Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) to improve HIT rates and reduce traffic to your origin.

* [Choose a cache level](https://developers.cloudflare.com/cache/how-to/set-caching-levels/)
* [Enable Tiered Cache with Argo](https://developers.cloudflare.com/cache/how-to/tiered-cache/#enable-tiered-cache)
* [Configure custom cache keys (Enterprise only)](https://developers.cloudflare.com/cache/how-to/cache-keys/)
* [Enable Prefetch URLs (Enterprise only)](https://developers.cloudflare.com/speed/optimization/content/prefetch-urls/)

## Secure your cache configuration

Control resources a client is allowed to load and set access permissions to allow different origins to access your origin's resources. Protect your site from web cache deception attacks while still caching static assets.

* [Avoid web cache poisoning attacks](https://developers.cloudflare.com/cache/cache-security/avoid-web-poisoning/)
* [Configure Cross-Origin Resource Sharing (CORS)](https://developers.cloudflare.com/cache/cache-security/cors/)
* [Enable Cache Deception Armor](https://developers.cloudflare.com/cache/cache-security/cache-deception-armor/#enable-cache-deception-armor)

## Features that alter cached content

Some Cloudflare features modify your HTML or cached objects at the edge to enable optimizations or security protections. These alterations only affect cached copies at Cloudflare's edge and do not change your original source files. Cloudflare removes the changes when you disable the feature and purge the cache. These alterations only affect cached copies at Cloudflare's edge and do not change your original source files. The changes are removed if the feature is disabled and the cache is purged.

* [Rocket Loader](https://developers.cloudflare.com/speed/optimization/content/rocket-loader/)
* [Polish](https://developers.cloudflare.com/images/polish/)
* [Hotlink Protection](https://developers.cloudflare.com/waf/tools/scrape-shield/hotlink-protection/)
* [Email address obfuscation](https://developers.cloudflare.com/waf/tools/scrape-shield/email-address-obfuscation/)
* [Bot Management JavaScript Detections](https://developers.cloudflare.com/bots/additional-configurations/javascript-detections/)

## Troubleshoot

Resolve common caching concerns.

* [Learn about Cloudflare's cache response statuses](https://developers.cloudflare.com/cache/concepts/cache-responses/)
* [Investigate Cloudflare's cache response with cURL](https://developers.cloudflare.com/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/#troubleshoot-requests-with-curl)
* [Diagnose Always Online issues](https://developers.cloudflare.com/cache/troubleshooting/always-online/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/get-started/","name":"Get started"}}]}
```

---

---
title: Interaction with Cloudflare products
description: How caching interacts with Workers, R2, WAF, and other products.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Interaction with Cloudflare products

Cloudflare caches content at data centers close to your visitors so your origin server handles fewer requests. The pages below explain how caching works when you also use Workers, R2 storage, or WAF security rules, and what to watch out for when combining them.

* [ Customize cache behavior with Workers ](https://developers.cloudflare.com/cache/interaction-cloudflare-products/workers/)
* [ How Workers interact with Cache Rules ](https://developers.cloudflare.com/cache/interaction-cloudflare-products/workers-cache-rules/)
* [ Enable cache in an R2 bucket ](https://developers.cloudflare.com/cache/interaction-cloudflare-products/r2/)
* [ Control cache access with WAF and Snippets ](https://developers.cloudflare.com/cache/interaction-cloudflare-products/waf-snippets/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/interaction-cloudflare-products/","name":"Interaction with Cloudflare products"}}]}
```

---

---
title: Enable cache in an R2 bucket
description: Serve cached content from R2 buckets through Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Enable cache in an R2 bucket

By default, R2 buckets are private. To serve R2 objects through Cloudflare's cache, you need to attach a domain name you control — called a [Custom Domain](https://developers.cloudflare.com/r2/buckets/public-buckets/#custom-domains) — to the bucket. This creates a public URL backed by Cloudflare's network, so requests for your stored files go through Cloudflare's cache instead of hitting R2 directly every time.

Follow these steps to set up a Custom Domain for your bucket:

1. Go to **R2** and select your bucket.
2. On the bucket page, select **Settings**.
3. Under **Public access** \> **Custom Domains**, select **Connect Domain**.
4. Enter the domain name you want to connect to and select **Continue**.
5. Review the new DNS record that will be added and select **Connect Domain**.

Cloudflare automatically adds a CNAME record that maps your domain to the bucket, generating a publicly available URL in the format `[name].domain.com`.

Note

The development URL (`r2.dev`) does not support caching, WAF, or bot management. You must use a Custom Domain for these features.

## Tiered Cache

By default, Cloudflare caches R2 content at edge data centers (the data centers closest to visitors) based on [cache rules](https://developers.cloudflare.com/cache/how-to/cache-rules/). Each edge data center that gets a cache miss fetches content directly from R2.

[Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) changes this by organizing data centers into a hierarchy. When a nearby data center has a cache miss, it first checks a designated upper-tier data center before going to R2\. This reduces the number of requests that reach R2.

To enable Tiered Cache for R2, configure [Smart Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/#smart-tiered-cache), which automatically selects the upper-tier data center with the lowest latency to your R2 bucket.

## Additional considerations

* **Access controls**: When you connect a Custom Domain, your R2 bucket becomes publicly accessible. Apply access controls to restrict who can request your files. Refer to [Control cache access with WAF and Snippets](https://developers.cloudflare.com/cache/interaction-cloudflare-products/waf-snippets/) for more information.
* **Cacheable size limits**: Files that exceed the [cacheable size limits](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#cacheable-size-limits) are not cached. Free, Pro, and Business plans have a limit of 512 MB per file. Enterprise plans default to 5 GB per file.
* **Default cached file types**: Cloudflare does not cache all file types by default. For example, HTML and JSON are not cached unless you create a [Cache Rule](https://developers.cloudflare.com/cache/how-to/cache-rules/) with the appropriate settings.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/interaction-cloudflare-products/","name":"Interaction with Cloudflare products"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/interaction-cloudflare-products/r2/","name":"Enable cache in an R2 bucket"}}]}
```

---

---
title: Control cache access with WAF and Snippets
description: Control cache access using WAF custom rules and Snippets.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Control cache access with WAF and Snippets

When you make an R2 bucket publicly accessible for caching (via a [Custom Domain](https://developers.cloudflare.com/r2/buckets/public-buckets/#custom-domains)), anyone who knows the URL can access the content. To restrict access, you can use Cloudflare's [WAF](https://developers.cloudflare.com/waf/custom-rules/use-cases/configure-token-authentication/) to validate requests before they reach the cache or your bucket.

The following diagram illustrates the flow of a request through WAF, Cache, and R2\. WAF custom rules run before cache rules in the [request pipeline](https://developers.cloudflare.com/ruleset-engine/reference/phases-list/), so invalid requests are blocked before consuming cache resources.

flowchart LR
accTitle: Connections with Cloudflare
A[User's request] --> B[WAF] --> C[Cache] --> D[R2]

  
## Presigned URLs

A presigned URL is a regular URL with a cryptographic token appended to it. The token contains a hash-based message authentication code (HMAC) computed from the URL path, a timestamp, and a secret key shared between the signing service and the validator. Anyone with the URL can access the content until the token expires, but the token cannot be reused for a different URL path.

You can presign URLs similar to [S3 ↗](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html), enabling you to share direct access to your content with an associated timeout. This approach can be implemented using a combination of Snippets, Rules, or Cloudflare Workers.

For optimal performance, we recommend separating the creation and validation processes:

* [Snippets](https://developers.cloudflare.com/rules/snippets/examples/signing-requests/) for HMAC creation (signing the URL)
* [WAF custom rules](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#hmac-validation) for HMAC validation (verifying the token on each request)

In the Workers documentation, the [Signing requests](https://developers.cloudflare.com/workers/examples/signing-requests/) example shows how to both generate and verify signed requests using HMAC. The Workers implementation is compatible with the WAF's [is\_timed\_hmac\_valid\_v0() validation function](https://developers.cloudflare.com/waf/custom-rules/use-cases/configure-token-authentication/), so you can sign with Workers and validate with WAF custom rules, or handle both in Workers.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/interaction-cloudflare-products/","name":"Interaction with Cloudflare products"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/interaction-cloudflare-products/waf-snippets/","name":"Control cache access with WAF and Snippets"}}]}
```

---

---
title: Customize cache behavior with Workers
description: Customize cache behavior with the Workers Cache API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Customize cache behavior with Workers

You can use [Workers](https://developers.cloudflare.com/workers/) to customize cache behavior on Cloudflare's network. Workers run as middleware in the request lifecycle — a single Worker handles both the request and response phases. When a request arrives, it hits the Worker before the cache is checked. The Worker can modify the incoming request (for example, rewrite the URL or add headers), then call `fetch()` to continue the request through the cache. When the response comes back — whether from cache or from the origin server — the Worker can also modify the response before it is sent to the visitor.

The diagram below illustrates a common interaction flow between Workers and Cache.

![Workers and cache flow example flow diagram.](https://developers.cloudflare.com/_astro/workers-cache-flow.DBEQRofC_ZP2BOU.webp) 
1. A visitor (a) requests a URL, and this request is directed to a Worker. The Worker can then interact with the request, either requesting the content from the origin server using (b) `fetch()` or sending a (f) response back to the visitor.
2. If the content is cached, the cache sends a (e) response back to the Worker, which can modify the response before sending a (f) response back to the visitor.
3. When using [cache rules](https://developers.cloudflare.com/cache/how-to/cache-rules/) with Workers, the cache rule must match the properties of the URL in the `fetch()` (b) request — such as headers, hostname, or URL path — not the original visitor URL/host (a). Otherwise, the rule will not be applied.

Here are a few examples of how Workers can be used to customize cache behavior:

* **Modify Response**: Adjust or enhance content after it is retrieved from the cache, ensuring that responses are up-to-date or tailored to specific needs.
* **Signed URLs**: Generate time-limited signed URLs to control access and enhance security.
* **Personalized Response**: Deliver personalized content based on user data while using cached resources to reduce the load on the origin server.
* **Reduce Latency**: Serve content from a data center close to the visitor, decreasing load times and improving the user experience.

You can also use [Snippets](https://developers.cloudflare.com/rules/snippets/) for lightweight modifications like header changes, redirects, and JWT validation without deploying a full Worker script. Snippets are included at no additional cost on all paid plans but have stricter resource limits (5 ms execution time, 32 KB package size).

Note

When using Workers and [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/) (a traffic routing configuration where requests pass through two Cloudflare zones), some caveats and limitations may apply.

## Cache features in Workers

Workers offer two ways to interact with the cache. Use `fetch()` when your Worker makes subrequests to an origin. Use the Cache API when your Worker generates responses without a backend origin.

* **fetch()**: When a Worker calls `fetch()`, the request passes through Cloudflare's cache and [Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) (if enabled). You can control caching behavior by setting properties on the request's [cf object](https://developers.cloudflare.com/workers/runtime-apis/request/#the-cf-property-requestinitcfproperties) — including time-to-live (TTL) values, custom cache keys, and cache headers. For more details, refer to [Cache using fetch](https://developers.cloudflare.com/workers/examples/cache-using-fetch/).
* **Cache API**: Allows you to programmatically store, retrieve, and delete responses in Cloudflare's cache using `caches.default` or `caches.open()`. Unlike `fetch()`, the Cache API only operates on the cache in the data center handling the current request — it does not interact with Tiered Cache. Use the Cache API when you need to cache responses that did not come from an origin. For more details, refer to [Using the Cache API](https://developers.cloudflare.com/workers/examples/cache-api/).

To understand more about how Cache and Workers interact, refer to [Cache in Workers](https://developers.cloudflare.com/workers/reference/how-the-cache-works/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/interaction-cloudflare-products/","name":"Interaction with Cloudflare products"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/interaction-cloudflare-products/workers/","name":"Customize cache behavior with Workers"}}]}
```

---

---
title: How Workers interact with Cache Rules
description: How Workers interact with Cache Rules execution.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# How Workers interact with Cache Rules

When you use both [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/) and [Workers](https://developers.cloudflare.com/workers/) on the same request, the Worker's cache settings take priority — but only when the required [compatibility flags](#compatibility-flags) are enabled.

Your Workers script can override Cache Rules behavior, whether the request is for a domain proxied through Cloudflare or a domain that is not. For example, if a Cache Rule is configured to bypass cache for `example.com/foo`, but your Workers script sets `cacheEverything: true` in the [cf object](https://developers.cloudflare.com/workers/runtime-apis/request/#the-cf-property-requestinitcfproperties) of a `fetch()` request, the Worker's setting takes precedence and the response is cached.

## Precedence order

Cache behavior is determined by the following order of precedence:

1. [Workers](https://developers.cloudflare.com/workers/) script settings
2. [Cache rules](https://developers.cloudflare.com/cache/how-to/cache-rules/)
3. [Page rules](https://developers.cloudflare.com/rules/page-rules/)

Workers override Cache Rules, and Cache Rules override Page Rules. When multiple rules at the same level match the same request, the [last matching rule wins](https://developers.cloudflare.com/cache/how-to/cache-rules/order/) for any conflicting settings.

## Compatibility flags

The override behavior is controlled by [compatibility flags](https://developers.cloudflare.com/workers/configuration/compatibility-flags/) — configuration settings that opt your Worker into specific runtime behaviors. There are two flags because Workers have two ways to interact with the cache:

* For the [Fetch API](https://developers.cloudflare.com/workers/runtime-apis/fetch/) (`fetch()` with `cf` properties): `request_cf_overrides_cache_rules`
* For the [Cache API](https://developers.cloudflare.com/workers/runtime-apis/cache/) (`caches.default.put()` / `caches.default.match()`): `cache_api_request_cf_overrides_cache_rules`

These flags must be enabled to allow Workers scripts to override Cache Rules. If the correct flag is not enabled for the API you are using, your Worker's cache settings are silently ignored and Cache Rules apply instead.

### Compatibility date behavior

A Worker's [compatibility date](https://developers.cloudflare.com/workers/configuration/compatibility-dates/) determines which flags are active by default. When you set a compatibility date, all flags with an enable date on or before that date are automatically turned on.

| Flag                                                         | Enabled by default                         | Prerequisite                       |
| ------------------------------------------------------------ | ------------------------------------------ | ---------------------------------- |
| request\_cf\_overrides\_cache\_rules (Fetch API)             | Compatibility dates on or after 2025-04-02 | None                               |
| cache\_api\_compat\_flags                                    | Compatibility dates on or after 2025-04-19 | None                               |
| cache\_api\_request\_cf\_overrides\_cache\_rules (Cache API) | Compatibility dates on or after 2025-05-19 | Requires cache\_api\_compat\_flags |

The Cache API has an extra requirement: `cache_api_compat_flags` must be enabled for any compatibility flags to take effect on the Cache API. Without it, the Cache API ignores all compatibility flags, even ones you explicitly list in your configuration.

If your Worker uses a compatibility date before the dates listed above, you must manually add the flags to your configuration. Otherwise, cache behavior follows Cache Rules instead of the Worker's settings.

### Example (Older compatibility date)

A Cache Rule bypasses cache for `example.com/foo`. A Worker with a compatibility date before `2025-04-02` sets `cacheEverything: true` via `fetch()`. Because the compatibility date is too old for `request_cf_overrides_cache_rules` to be active by default, the Cache Rule wins and the response is not cached.

Similarly, if you use the Cache API and your compatibility date is before `2025-04-19`, `cache_api_compat_flags` is not active. Even if you manually add `cache_api_request_cf_overrides_cache_rules` to your configuration, it has no effect because the Cache API does not recognize compatibility flags without `cache_api_compat_flags`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/interaction-cloudflare-products/","name":"Interaction with Cloudflare products"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/interaction-cloudflare-products/workers-cache-rules/","name":"How Workers interact with Cache Rules"}}]}
```

---

---
title: Changelog
description: Track the latest updates and changes to Cloudflare Cache features.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Changelog

[ Subscribe to RSS ](https://developers.cloudflare.com/changelog/rss/cache.xml) 

## 2026-05-26

  
**BYPASS status now returned for uncacheable responses**   

Cloudflare now returns a `BYPASS` [cache status](https://developers.cloudflare.com/cache/concepts/cache-responses/) whenever a response is not cacheable, instead of the previous mix of `BYPASS` and `MISS` that depended on why Cloudflare chose not to cache the response.

There are multiple reasons Cloudflare may refuse to cache a response — for example, the response exceeds the [maximum cacheable file size](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#cacheable-size-limits) for your plan, the origin sends `Cache-Control: no-cache`, `private`, or `max-age=0`, the response includes a `Set-Cookie` header, or the request includes an `Authorization` header.

Previously, only some of these conditions returned `BYPASS`. Others — such as responses exceeding the maximum cacheable file size — returned `MISS` on every request, regardless of whether [Origin Cache Control](https://developers.cloudflare.com/cache/concepts/cache-control/#origin-cache-control-behavior) was on or off. Because the response could never be cached, every subsequent request also returned `MISS`, which looked indistinguishable from a broken cache and made it hard to tell whether Cloudflare was trying and failing to cache the asset or had deliberately chosen not to cache it.

`BYPASS` now consistently signals that Cloudflare refused to cache the response, regardless of the reason. `MISS` is reserved for cacheable responses that simply were not in the local cache at request time.

#### What to expect in your analytics

After this change rolls out, you should see:

* **MISS rate decreases**: Uncacheable responses no longer count as cache misses.
* **BYPASS rate increases**: These same responses are now reported as bypasses.
* **Cache hit ratio increases**: Hit ratio calculations no longer include uncacheable traffic that could never have been cached, giving you a more accurate view of cache effectiveness.

Your total request volume and origin traffic are unchanged — only the cache status label is different.

#### Browser cache TTL behavior is preserved

The cache status label is the only thing changing — browser cache TTL handling for any given response is identical to what it was before:

* Responses that historically returned `MISS` because Cloudflare refused to cache them (for example, responses over the maximum cacheable file size) now return `BYPASS`, but continue to have browser cache TTL applied — exactly as they did when they were labeled `MISS`.
* Responses that historically returned `BYPASS` and skipped browser cache TTL continue to skip browser cache TTL.

In both cases, the decision to apply browser cache TTL depends on the underlying reason Cloudflare did not cache the response, not on the new `BYPASS` label.

## 2026-05-04

  
**Pingora now powers Cloudflare's cache**   

Cloudflare's cache now runs on a new proxy built on [Pingora ↗](https://github.com/cloudflare/pingora), the Rust-based framework that already serves a significant portion of Cloudflare's network traffic. The new proxy is faster, more memory-safe, and designed to evolve our cache architecture. It delivers immediate performance improvements and enables new caching capabilities.

#### What this brings

* **Lower latency**: The new proxy reduces per-request overhead through improved connection reuse.
* **Reduced cache MISSes**: Enhanced cache retention improves origin offload.
* **Better RFC compliance**: Caching behavior more closely follows HTTP caching standards.
* **Foundation for future features**: The new architecture enables upcoming improvements to cache functionality and efficiency.

#### New features

* **Asynchronous `stale-while-revalidate`**: Every request returns stale content immediately while revalidation happens in the background, instead of the first request after expiry blocking on the origin. Refer to the [asynchronous stale-while-revalidate changelog](https://developers.cloudflare.com/changelog/post/2026-02-26-async-stale-while-revalidate/) for details.
* **Unbuffered bypass by default**: Responses that bypass cache are streamed directly to the client without buffering, reducing time-to-first-byte for uncacheable content.

#### Behavioral changes

The new architecture introduces the following behavioral changes to improve RFC compliance and correctness:

* **`Vary: *` results in cache bypass**: According to [RFC 9110 Section 12.5.5 ↗](https://httpwg.org/specs/rfc9110.html#field.vary), a `Vary` header value of `*` indicates the response varies on factors beyond request headers and must not be served from cache. Cloudflare now bypasses cache for these responses instead of storing them.
* **`Set-Cookie` stripped on MISS and EXPIRED**: For cacheable assets, `Set-Cookie` is now stripped on MISS and EXPIRED responses, not only on HITs.
* **Floating-point TTL values**: Floating-point time-to-live values (for example, `max-age=1.5`) are rounded down to the nearest integer instead of being rejected as invalid.

#### What's next

A deeper look at the new cache proxy is coming soon to the [Cloudflare blog ↗](https://blog.cloudflare.com/). For background on the underlying framework, read:

* [Open sourcing Pingora: our Rust framework for building programmable network services ↗](https://blog.cloudflare.com/pingora-open-source/)
* [How we built Pingora, the proxy that connects Cloudflare to the Internet ↗](https://blog.cloudflare.com/how-we-built-pingora-the-proxy-that-connects-cloudflare-to-the-internet/)

## 2026-04-27

  
**Cache Response Rules now support zone versioning**   

Cache Response Rules now work with [Version Management](https://developers.cloudflare.com/version-management/). You can version response-phase cache settings and promote them through environments, just like Cache Rules and other supported configurations.

#### What changed

Previously, Cache Response Rules were excluded from zone versioning. Any response-phase rule you created applied globally across all environments with no way to test changes in staging first. Cache Rules already supported versioning, but the response phase, where you modify `Cache-Control` directives, manage cache tags, and strip headers, did not.

Cache Response Rules are now fully integrated with Version Management. You can create or modify response-phase rules within a version, and those changes stay scoped to that version until promoted.

#### Benefits

* **Safe rollout of cache behavior changes**: Test response-phase rules in a staging environment before promoting to production. Catch unintended caching side effects early.
* **Parity with Cache Rules**: Cache Response Rules now follow the same versioning workflow as Cache Rules, so you can manage all cache configuration through a single promotion pipeline.
* **Independent environment control**: Run different response-phase cache settings per environment. For example, strip `Set-Cookie` headers in staging to validate cacheability without affecting production traffic.

#### Get started

Configure Cache Response Rules in the [Cloudflare dashboard ↗](https://dash.cloudflare.com/?to=/:account/:zone/caching/cache-rules) under **Caching** \> **Cache Rules**, or via the [Rulesets API](https://developers.cloudflare.com/ruleset-engine/rulesets-api/). For more details, refer to the [Cache Response Rules documentation](https://developers.cloudflare.com/cache/how-to/cache-response-rules/) and the [Version Management documentation](https://developers.cloudflare.com/version-management/).

## 2026-04-17

  
**Smart Tiered Cache optimizes public cloud origins**   

You can now achieve higher cache HIT rates and reduce origin load for origins hosted on public cloud providers with [Smart Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/#smart-tiered-cache). By setting a cloud region hint for your origin, Cloudflare selects the optimal upper-tier data center for that cloud region, funneling all cache MISSes through a single location close to your origin.

Previously, Smart Tiered Cache could not reliably select an optimal upper tier for origins behind anycast or regional unicast networks commonly used by cloud providers. Origins on AWS, GCP, Azure, and Oracle Cloud would fall back to a multi-upper-tier topology, resulting in lower cache HIT rates and more requests reaching your origin.

#### How it works

Set a cloud region hint (for example, `aws/us-east-1` or `gcp/europe-west1`) for your origin IP or hostname. Smart Tiered Cache uses this hint along with real-time latency data to select a primary upper tier close to your cloud region, plus a fallback in a different location for resilience.

* **Supported providers**: AWS, GCP, Azure, and Oracle Cloud.
* **All plans**: Available on Free, Pro, Business, and Enterprise plans at no additional cost.
* **Dashboard and API**: Configure from **Caching** \> **Tiered Cache** \> **Origin Configuration**, or use the API and Terraform.

#### Get started

To get started, enable [Smart Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) and set a cloud region hint for your origin in the [Tiered Cache settings](https://developers.cloudflare.com/cache/how-to/tiered-cache/#public-cloud-origins).

## 2026-03-24

  
**Cache Response Rules**   

You can now control how Cloudflare handles origin responses without changing your origin. Cache Response Rules let you modify `Cache-Control` directives, manage cache tags, and strip headers like `Set-Cookie` from origin responses _before_ they reach Cloudflare's cache. Whether traffic is cached or passed through dynamically, these rules give you control over origin response behavior that was previously out of reach.

#### What changed

Cache Rules previously only operated on request attributes. Cache Response Rules introduce a new response phase that evaluates origin responses and lets you act on them before caching. You can now:

* **Modify `Cache-Control` directives**: Set or remove individual directives like `no-store`, `no-cache`, `max-age`, `s-maxage`, `stale-while-revalidate`, `immutable`, and more. For example, remove a `no-cache` directive your origin sends so Cloudflare can cache the asset, or set an `s-maxage` to control how long Cloudflare stores it.
* **Set a different browser `Cache-Control`**: Send a different `Cache-Control` header downstream to browsers and other clients than what Cloudflare uses internally, giving you independent control over edge and browser caching strategies.
* **Manage cache tags**: Add, set, or remove cache tags on responses, including converting tags from another CDN's header format into Cloudflare's `Cache-Tag` header. This is especially useful if you are migrating from a CDN that uses a different tag header or delimiter.
* **Strip headers that block caching**: Remove `Set-Cookie`, `ETag`, or `Last-Modified` headers from origin responses before caching, so responses that would otherwise be treated as uncacheable can be stored and served from cache.

#### Benefits

* **No origin changes required**: Fix caching behavior entirely from Cloudflare, even when your origin configuration is locked down or managed by a different team.
* **Simpler CDN migration**: Match caching behavior from other CDN providers without rewriting your origin. Translate cache tag formats and override directives that do not align with Cloudflare's defaults.
* **Native support, fewer workarounds**: Functionality that previously required workarounds is now built into Cache Rules with full Tiered Cache compatibility.
* **Fine-grained control**: Use expressions to match on request and response attributes, then apply precise cache settings per rule. Rules are stackable and composable with existing Cache Rules.

#### Get started

Configure Cache Response Rules in the [Cloudflare dashboard ↗](https://dash.cloudflare.com/?to=/:account/:zone/caching/cache-rules) under **Caching** \> **Cache Rules**, or via the [Rulesets API ↗](https://developers.cloudflare.com/ruleset-engine/rulesets-api/). For more details, refer to the [Cache Rules documentation ↗](https://developers.cloudflare.com/cache/how-to/cache-response-rules/).

## 2026-02-26

  
**Asynchronous stale-while-revalidate**   

Cloudflare's [stale-while-revalidate](https://developers.cloudflare.com/cache/concepts/cache-control/#revalidation) support is now fully asynchronous. Previously, the first request for a stale (expired) asset in cache had to wait for an origin response, after which that visitor received a REVALIDATED or EXPIRED status. Now, the first request after the asset expires triggers revalidation in the background and immediately receives stale content with an UPDATING status. All following requests also receive stale content with an `UPDATING` status until the origin responds, after which subsequent requests receive fresh content with a `HIT` status.

`stale-while-revalidate` is a `Cache-Control` directive set by your origin server that allows Cloudflare to serve an expired cached asset while a fresh copy is fetched from the origin.

Asynchronous revalidation brings:

* **Lower latency**: No visitor is waiting for the origin when the asset is already in cache. Every request is served from cache during revalidation.
* **Consistent experience**: All visitors receive the same cached response during revalidation.
* **Reduced error exposure**: The first request is no longer vulnerable to origin timeouts or errors. All visitors receive a cached response while revalidation happens in the background.

#### Availability

This change is live for all Free, Pro, and Business zones. Approximately 75% of Enterprise zones have been migrated, with the remaining zones rolling out throughout the quarter.

#### Get started

To use this feature, make sure your origin includes the `stale-while-revalidate` directive in the `Cache-Control` header. Refer to the [Cache-Control documentation](https://developers.cloudflare.com/cache/concepts/cache-control/#revalidation) for details.

## 2025-11-25

  
**Audit Logs for Cache Purge Events**   

You can now review detailed audit logs for cache purge events, giving you visibility into what purge requests were sent, what they contained, and by whom. Audit your purge requests via the Dashboard or API for all purge methods:

* Purge everything
* List of prefixes
* List of tags
* List of hosts
* List of files

#### Example

The detailed audit payload is visible within the Cloudflare Dashboard (under **Manage Account** \> **Audit Logs**) and via the API. Below is an example of the Audit Logs v2 payload structure:

```

{

  "action": {

    "result": "success",

    "type": "create"

  },

  "actor": {

    "id": "1234567890abcdef",

    "email": "user@example.com",

    "type": "user"

  },

  "resource": {

    "product": "purge_cache",

    "request": {

      "files": [

        "https://example.com/images/logo.png",

        "https://example.com/css/styles.css"

      ]

    }

  },

  "zone": {

    "id": "023e105f4ecef8ad9ca31a8372d0c353",

    "name": "example.com"

  }

}


```

#### Get started

To get started, refer to the [Audit Logs documentation](https://developers.cloudflare.com/fundamentals/account/account-security/audit-logs/).

## 2025-11-07

  
**Inspect Cache Keys with Cloudflare Trace**   

You can now see the exact cache key generated for any request directly in Cloudflare Trace. This visibility helps you troubleshoot cache hits and misses, and verify that your Custom Cache Keys — configured via Cache Rules or Page Rules — are working as intended.

Previously, diagnosing caching behavior required inferring the key from configuration settings. Now, you can confirm that your custom logic for headers, query strings, and device types is correctly applied.

Access Trace via the [dashboard](https://developers.cloudflare.com/rules/trace-request/how-to/#use-trace-in-the-dashboard) or [API](https://developers.cloudflare.com/api/resources/request%5Ftracer/methods/trace/), either manually for ad-hoc debugging or automated as part of your quality-of-service monitoring.

#### Example scenario

If you have a Cache Rule that segments content based on a specific cookie (for example, `user_region`), run a Trace with that cookie present to confirm the `user_region` value appears in the resulting cache key.

The Trace response includes the cache key in the `cache` object:

```

{

  "step_name": "request",

  "type": "cache",

  "matched": true,

  "public_name": "Cache Parameters",

  "cache": {

    "key": {

      "zone_id": "023e105f4ecef8ad9ca31a8372d0c353",

      "scheme": "https",

      "host": "example.com",

      "uri": "/images/hero.jpg"

    },

    "key_string": "023e105f4ecef8ad9ca31a8372d0c353::::https://example.com/images/hero.jpg:::::"

  }

}


```

#### Get started

To learn more, refer to the [Trace documentation](https://developers.cloudflare.com/rules/trace-request/) and our guide on [Custom Cache Keys](https://developers.cloudflare.com/cache/how-to/cache-keys/).

## 2025-08-29

  
**Smart Tiered Cache Fallback to Generic**   

[Smart Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/#smart-tiered-cache) now falls back to [Generic Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/#generic-global-tiered-cache) when the origin location cannot be determined, improving cache precision for your content.

Previously, when Smart Tiered Cache was unable to select the optimal upper tier (such as when origins are masked by Anycast IPs), latency could be negatively impacted. This fallback now uses Generic Tiered Cache instead, providing better performance and cache efficiency.

#### How it works

When Smart Tiered Cache falls back to Generic Tiered Cache:

1. **Multiple upper-tiers**: Uses all of Cloudflare's global data centers as a network of upper-tiers instead of a single optimal location.
2. **Distributed cache requests**: Lower-tier data centers can query any available upper-tier for cached content.
3. **Improved global coverage**: Provides better cache hit ratios across geographically distributed visitors.
4. **Automatic fallback**: Seamlessly transitions when origin location cannot be determined, such as with Anycast-masked origins.

#### Benefits

* **Preserves high performance during fallback**: Smart Tiered Cache now maintains strong cache efficiency even when optimal upper tier selection is not possible.
* **Minimizes latency impact**: Automatically uses Generic Tiered Cache topology to keep performance high when origin location cannot be determined.
* **Seamless experience**: No configuration changes or intervention required when fallback occurs.
* **Improved resilience**: Smart Tiered Cache remains effective across diverse origin infrastructure, including Anycast-masked origins.

#### Get started

This improvement is automatically applied to all zones using [Smart Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/). No action is required on your part.

## 2025-04-04

  
**Workers Fetch API can override Cache Rules**   

You can now programmatically override Cache Rules using the `cf` object in the `fetch()` command. This feature gives you fine-grained control over caching behavior on a per-request basis, allowing Workers to customize cache settings dynamically based on request properties, user context, or business logic.

#### How it works

Using the `cf` object in `fetch()`, you can override specific Cache Rules settings by:

1. **Setting custom cache options**: Pass cache properties in the `cf` object as the second argument to `fetch()` to override default Cache Rules.
2. **Dynamic cache control**: Apply different caching strategies based on request headers, cookies, or other runtime conditions.
3. **Per-request customization**: Bypass or modify Cache Rules for individual requests while maintaining default behavior for others.
4. **Programmatic cache management**: Implement complex caching logic that adapts to your application's needs.

#### What can be configured

Workers can override the following Cache Rules settings through the `cf` object:

* **`cacheEverything`**: Treat all content as static and cache all file types beyond the default cached content.
* **`cacheTtl`**: Set custom time-to-live values in seconds for cached content at the edge, regardless of origin headers.
* **`cacheTtlByStatus`**: Set different TTLs based on the response status code (for example, `{ "200-299": 86400, 404: 1, "500-599": 0 }`).
* **`cacheKey`**: Customize cache keys to control which requests are treated as the same for caching purposes (Enterprise only).
* **`cacheTags`**: Append additional cache tags for targeted cache purging operations.

#### Benefits

* **Enhanced flexibility**: Customize cache behavior without modifying zone-level Cache Rules.
* **Dynamic optimization**: Adjust caching strategies in real-time based on request context.
* **Simplified configuration**: Reduce the number of Cache Rules needed by handling edge cases programmatically.
* **Improved performance**: Fine-tune cache behavior for specific use cases to maximize hit rates.

#### Get started

To get started, refer to the [Workers Fetch API documentation](https://developers.cloudflare.com/workers/runtime-apis/fetch/) and the [cf object properties documentation](https://developers.cloudflare.com/workers/runtime-apis/request/#the-cf-property-requestinitcfproperties).

## 2025-04-03

  
**All cache purge methods now available for all plans**   

You can now access all Cloudflare cache purge methods — no matter which plan you’re on. Whether you need to update a single asset or instantly invalidate large portions of your site’s content, you now have the same powerful tools previously reserved for Enterprise customers.

**Anyone on Cloudflare can now:**

1. [Purge Everything](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-everything/): Clears all cached content associated with a website.
2. [Purge by Prefix](https://developers.cloudflare.com/cache/how-to/purge-cache/purge%5Fby%5Fprefix/): Targets URLs sharing a common prefix.
3. [Purge by Hostname](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-hostname/): Invalidates content by specific hostnames.
4. [Purge by URL (single-file purge)](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-single-file/): Precisely targets individual URLs.
5. [Purge by Tag](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-tags/): Uses Cache-Tag response headers to invalidate grouped assets, offering flexibility for complex cache management scenarios.

Want to learn how each purge method works, when to use them, or what limits apply to your plan? Dive into our [purge cache documentation](https://developers.cloudflare.com/cache/how-to/purge-cache/) and [API reference ↗](https://developers.cloudflare.com/api/resources/cache/methods/purge/) for all the details.

## 2025-02-12

  
**Configurable multiplexing HTTP/2 to Origin**   

You can now configure HTTP/2 multiplexing settings for origin connections on Enterprise plans. This feature allows you to optimize how Cloudflare manages concurrent requests over HTTP/2 connections to your origin servers, improving cache efficiency and reducing connection overhead.

#### How it works

HTTP/2 multiplexing allows multiple requests to be sent over a single TCP connection. With this configuration option, you can:

1. **Control concurrent streams**: Adjust the maximum number of concurrent streams per connection.
2. **Optimize connection reuse**: Fine-tune connection pooling behavior for your origin infrastructure.
3. **Reduce connection overhead**: Minimize the number of TCP connections required between Cloudflare and your origin.
4. **Improve cache performance**: Better connection management can enhance cache fetch efficiency.

#### Benefits

* **Customizable performance**: Tailor multiplexing settings to your origin's capabilities.
* **Reduced latency**: Fewer connection handshakes improve response times.
* **Lower origin load**: More efficient connection usage reduces server resource consumption.
* **Enhanced scalability**: Better connection management supports higher traffic volumes.

#### Get started

Enterprise customers can configure HTTP/2 multiplexing settings in the [Cloudflare Dashboard ↗](https://dash.cloudflare.com/) or through our [API](https://developers.cloudflare.com/api/).

Important consideration

This setting needs to be tuned carefully for your origin infrastructure. Setting the concurrent stream limit too high can negatively impact performance by saturating the shared TCP connection and overwhelming server processing capacity, leading to increased latency for individual requests.

## 2025-02-04

  
**Fight CSAM More Easily Than Ever**   

You can now implement our **child safety tooling**, the **[CSAM Scanning Tool](https://developers.cloudflare.com/cache/reference/csam-scanning/)**, more easily. Instead of requiring external reporting credentials, you only need a verified email address for notifications to onboard. This change makes the tool more accessible to a wider range of customers.

**How It Works**

When enabled, the tool automatically [hashes images for enabled websites as they enter the Cloudflare cache ↗](https://blog.cloudflare.com/the-csam-scanning-tool/). These hashes are then checked against a database of **known abusive images**.

* **Potential match detected?**  
   * The **content URL is blocked**, and  
   * **Cloudflare will notify you** about the found matches via the provided email address.

**Updated Service-Specific Terms**

We have also made updates to our **[Service-Specific Terms ↗](https://www.cloudflare.com/service-specific-terms-application-services/#csam-scanning-tool-terms)** to reflect these changes.

## 2025-01-08

  
**Smart Tiered Cache optimizes Load Balancing Pools**   

You can now achieve higher cache hit rates and reduce origin load when using [Load Balancing](https://developers.cloudflare.com/load-balancing/) with [Smart Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/). Cloudflare automatically selects a single, optimal tiered data center for all origins in your Load Balancing Pool.

#### How it works

When you use [Load Balancing](https://developers.cloudflare.com/load-balancing/) with [Smart Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/), Cloudflare analyzes performance metrics across your pool's origins and automatically selects the optimal Upper Tier data center for the entire pool. This means:

* **Consistent cache location**: All origins in the pool share the same Upper Tier cache.
* **Higher HIT rates**: Requests for the same content hit the cache more frequently.
* **Reduced origin requests**: Fewer requests reach your origin servers.
* **Improved performance**: Faster response times for cache HITs.

#### Example workflow

```

Load Balancing Pool: api-pool

├── Origin 1: api-1.example.com

├── Origin 2: api-2.example.com

└── Origin 3: api-3.example.com

    ↓

Selected Upper Tier: [Optimal data center based on pool performance]


```

#### Get started

To get started, enable [Smart Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) on your zone and configure your [Load Balancing Pool](https://developers.cloudflare.com/load-balancing/).

## 2024-11-20

  
**Smart Tiered Cache automatically optimizes R2 caching**   

You can now reduce latency and lower R2 egress costs automatically when using [Smart Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) with [R2](https://developers.cloudflare.com/r2/). Cloudflare intelligently selects a tiered data center close to your R2 bucket location, creating an efficient caching topology without additional configuration.

#### How it works

When you enable [Smart Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) for zones using [R2](https://developers.cloudflare.com/r2/) as an origin, Cloudflare automatically:

1. **Identifies your R2 bucket location**: Determines the geographical region where your R2 bucket is stored.
2. **Selects an optimal Upper Tier**: Chooses a data center close to your bucket as the common Upper Tier cache.
3. **Routes requests efficiently**: All cache misses in edge locations route through this Upper Tier before reaching R2.

#### Benefits

* **Automatic optimization**: No manual configuration required.
* **Lower egress costs**: Fewer requests to R2 reduce egress charges.
* **Improved hit ratio**: Common Upper Tier increases cache efficiency.
* **Reduced latency**: Upper Tier proximity to R2 minimizes fetch times.

#### Get started

To get started, enable [Smart Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) on your zone using R2 as an origin.

## 2024-11-07

  
**Stage and test cache configurations safely**   

You can now stage and test cache configurations before deploying them to production. Versioned environments let you safely validate cache rules, purge operations, and configuration changes without affecting live traffic.

#### How it works

With versioned environments, you can:

1. **Create staging versions** of your cache configuration.
2. **Test cache rules** in a non-production environment.
3. **Purge staged content** independently from production.
4. **Validate changes** before promoting to production.

This capability integrates with Cloudflare's broader [versioning system](https://developers.cloudflare.com/version-management/), allowing you to manage cache configurations alongside other zone settings.

#### Benefits

* **Risk-free testing**: Validate configuration changes without impacting production.
* **Independent purging**: Clear staging cache without affecting live content.
* **Deployment confidence**: Catch issues before they reach end users.
* **Team collaboration**: Multiple team members can work on different versions.

#### Get started

To get started, refer to the [version management documentation](https://developers.cloudflare.com/version-management/).

Important limitation

Cache Reserve is only supported for your production environment. Staged environments can use standard cache functionality, but Cache Reserve persistence is limited to production deployments.

## 2024-11-07

  
**Shard cache using custom cache key values**   

Enterprise customers can now optimize cache hit ratios for content that varies by device, language, or referrer by **sharding cache** using up to ten values from previously restricted headers with [custom cache keys](https://developers.cloudflare.com/cache/how-to/cache-keys/).

#### How it works

When configuring [custom cache keys](https://developers.cloudflare.com/cache/how-to/cache-keys/), you can now include values from these headers to create distinct cache entries:

* **`accept*` headers** (for example, `accept`, `accept-encoding`, `accept-language`): Serve different cached versions based on content negotiation.
* **`referer` header**: Cache content differently based on the referring page or site.
* **`user-agent` header**: Maintain separate caches for different browsers, devices, or bots.

#### When to use cache sharding

* Content varies significantly by device type (mobile vs desktop).
* Different language or encoding preferences require distinct responses.
* Referrer-specific content optimization is needed.

#### Example configuration

```

{

  "cache_key": {

    "custom_key": {

      "header": {

        "include": ["accept-language", "user-agent"],

        "check_presence": ["referer"]

      }

    }

  }

}


```

This configuration creates separate cache entries based on the `accept-language` and `user-agent` headers, while also considering whether the `referer` header is present.

#### Get started

To get started, refer to the [custom cache keys documentation](https://developers.cloudflare.com/cache/how-to/cache-keys/).

Note

While cache sharding can improve hit ratios for specific use cases, overly sharding your cache can reduce overall cache efficiency and negatively impact performance. Carefully evaluate whether sharding benefits your specific traffic patterns.

## 2024-09-05

  
**One-click Cache Rules templates now available**   

You can now create optimized cache rules instantly with **one-click templates**, eliminating the complexity of manual rule configuration.

#### How it works

1. Navigate to **Rules** \> **Templates** in your Cloudflare dashboard.
2. Select a template for your use case.
3. Click to apply the template with sensible defaults.
4. Customize as needed for your specific requirements.

#### Available cache templates

* **Cache everything**: Adjust the cache level for all requests.
* **Bypass cache for everything**: Bypass cache for all requests.
* **Cache default file extensions**: Replicate Page Rules caching behavior by making only default extensions eligible for cache.
* **Bypass cache on cookie**: Bypass cache for requests containing specific cookies.
* **Set edge cache time**: Cache responses with status code between 200 and 599 on the Cloudflare edge.
* **Set browser cache time**: Adjust how long a browser should cache a resource.

#### Get started

To get started, go to [**Rules > Templates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/caching/cache-rules) in the dashboard. For more information, refer to the [Cache Rules documentation](https://developers.cloudflare.com/cache/how-to/cache-rules/).

## 2024-07-19

  
**Regionalized Generic Tiered Cache for higher hit ratios**   

You can now achieve higher cache hit ratios with [Generic Global Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/#generic-global-tiered-cache). Regional content hashing routes content consistently to the same upper-tier data centers, eliminating redundant caching and reducing origin load.

#### How it works

Regional content hashing groups data centers by region and uses consistent hashing to route content to designated upper-tier caches:

* Same content always routes to the same upper-tier data center within a region.
* Eliminates redundant copies across multiple upper-tier caches.
* Increases the likelihood of cache HITs for the same content.

#### Example

A popular image requested from multiple edge locations in a region:

* **Before**: Cached at 3-4 different upper-tier data centers
* **After**: Cached at 1 designated upper-tier data center
* **Result**: 3-4x fewer cache MISSes, reducing origin load and improving performance

#### Get started

To get started, enable [Generic Global Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/#generic-global-tiered-cache) on your zone.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/changelog/","name":"Changelog"}}]}
```

---

---
title: Cache Reserve
description: Persist cached content in R2 storage to eliminate cache evictions.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache Reserve

Smart Shield

This functionality is now offered as part of Cloudflare's origin server safeguard, Smart Shield. [Learn more](https://developers.cloudflare.com/smart-shield/).

Cache Reserve is a large, persistent data store [implemented on top of R2](https://developers.cloudflare.com/r2/). By pushing a single button in the dashboard, your website's cacheable content will be written to Cache Reserve.

In the same way that Tiered Cache builds a hierarchy of caches between your visitors and your origin, Cache Reserve serves as the ultimate upper-tier cache, that will reserve storage space for your assets for as long as you want. This ensures that your content is served from cache longer, shielding your origin from unneeded egress fees.

![Content served from origin and getting cached in Cache Reserve, and Edge Cache Data Centers \(T1=upper-tier, T2=lower-tier\) on its way back to the client](https://developers.cloudflare.com/_astro/content-being-served.6zIZl3YT_1WqRl0.webp) 

Content in Cache Reserve is considered fresh based on the [Edge Cache TTL](https://developers.cloudflare.com/cache/how-to/edge-browser-cache-ttl/#edge-cache-ttl) setting, or your origin's `Cache-Control` headers if Edge Cache TTL is not set. After the freshness period expires, Cloudflare revalidates the asset with your origin the next time it is requested. This is the same behavior as in Cloudflare's regular CDN.

The retention period controls how long an asset stays in Cache Reserve before it is removed. Cache Reserve starts with a retention period of 30 days. If an asset is not requested within the retention period, it is removed from Cache Reserve. Requesting the asset resets the retention period.

Assets must [meet certain criteria](#cache-reserve-asset-eligibility) to use Cache Reserve.

Cache Reserve is a usage-based product and [pricing](#pricing) is detailed below. While Cache Reserve does require a paid plan, users can continue to use Cloudflare’s CDN (without Cache Reserve) for free.

## Enable Cache Reserve

A paid Cache Reserve plan is required.

* [ Dashboard ](#tab-panel-6815)
* [ API ](#tab-panel-6816)

1. In the Cloudflare dashboard, go to the **Cache Reserve** page.  
[ Go to **Cache Reserve** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/cache-reserve)
2. Select **Enable storage sync**.

Refer to the [Change Cache Reserve setting API](https://developers.cloudflare.com/api/resources/cache/subresources/cache%5Freserve/methods/edit/) for more information.

Note

You can pause Cache Reserve at any time. Pausing Cache Reserve means that Cloudflare’s network will no longer use Cache Reserve to serve data, but resources will remain in storage until they are purged or expired.

If you are an Enterprise customer and are interested in Cache Reserve, contact your account team to get help with your configuration.

## Cache Reserve asset eligibility

Not all assets are eligible for Cache Reserve. To be admitted into Cache Reserve, assets must:

* Be cacheable, according to Cloudflare's standard [cacheability factors](https://developers.cloudflare.com/cache/).
* Have a freshness time-to-live (TTL) of at least 10 hours (set by any means such as Cache-Control / [CDN-Cache-Control](https://developers.cloudflare.com/cache/concepts/cache-control/) origin response headers, [Edge Cache TTL](https://developers.cloudflare.com/cache/how-to/edge-browser-cache-ttl/#edge-cache-ttl), [Cache TTL By Status](https://developers.cloudflare.com/cache/how-to/configure-cache-status-code/), or [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/)),
* Have a Content-Length response header.
* When using [Image transformations](https://developers.cloudflare.com/images/optimization/hosted-images/create-variants/), original files are eligible for Cache Reserve, but resized file variants are not eligible because transformations happen after Cache Reserve in the response flow.

## Limits

* Cache Reserve file limits are the same as [R2 limits](https://developers.cloudflare.com/r2/platform/limits/). Note that [CDN cache limits](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#customization-options-and-limits) still apply. Assets larger than standard limits will not be stored in the standard CDN cache, so these assets will incur Cache Reserve operations costs far more frequently.
* Origin Range requests are not supported at this time from Cache Reserve.
* [Vary for images](https://developers.cloudflare.com/cache/advanced-configuration/vary-for-images/) is currently not compatible with Cache Reserve.
* Requests to [R2 public buckets linked to a zone's domain](https://developers.cloudflare.com/r2/buckets/public-buckets/) will not use Cache Reserve. Enabling Cache Reserve for the connected zone will use Cache Reserve only for requests not destined for the R2 bucket.
* Cache Reserve makes requests for uncompressed content directly from the origin. Unlike the standard Cloudflare CDN, Cache Reserve does not include the `Accept-Encoding: gzip` header when sending requests to the origin.
* Cache Reserve is bypassed when using the Cloudflare [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/) setup.

## Usage

Like the standard CDN, Cache Reserve also uses the `cf-cache-status` header to indicate [cache response statuses](https://developers.cloudflare.com/cache/concepts/cache-responses/) like `MISS`, `HIT`, and `REVALIDATED`. Cache Reserve cache misses and hits are factored into the dashboard's cache hit ratio.

Individual sampled requests that filled or were served by Cache Reserve are viewable via the [CacheReserveUsed](https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/zone/http%5Frequests/) Logpush field.

Cache Reserve monthly operations and storage usage are viewable in the dashboard.

## Pricing

Cache Reserve charges based on the total volume of data stored, along with two classes of operations on that data:

* [Class A operations](https://developers.cloudflare.com/r2/pricing/#class-a-operations) which are more expensive and tend to mutate state.
* [Class B operations](https://developers.cloudflare.com/r2/pricing/#class-b-operations) which tend to read existing state.

In most cases, a Cache Reserve miss will result in both one class A and one class B operation, and a Cache Reserve hit will result in one class B operation. Assets larger than 1 GB will incur more operations proportional to their size.

### Cache Reserve pricing

| Rates                       | |  Storage               | $0.015 / GB-month |
| --------------------------- | ------------------------ | ----------------- |
| Class A Operations (writes) | $4.50 / million requests |                   |
| Class B Operations (reads)  | $0.36 / million requests |                   |

Note

The billable quantity is rounded up to the nearest million.

### Storage usage

Storage is billed using gigabyte-month (GB-month) as the billing metric. A GB-month is calculated by recording total bytes stored for the duration of the month.

For example:

* Storing 1 GB for 30 days will be charged as 1 GB-month.
* Storing 2 GB for 15 days will be charged as 1 GB-month.

### Operations

Operations are performed by Cache Reserve on behalf of the user to write data from the origin to Cache Reserve and to pass that data downstream to other parts of Cloudflare’s network. These operations are managed internally by Cloudflare.

#### Class A operations (writes)

Class A operations are performed based on cache misses from Cloudflare’s CDN. When a request cannot be served from cache, it will be fetched from the origin and written to cache reserve as well as our edge caches on the way back to the visitor.

#### Class B operations (reads)

Class B operations are performed when data needs to be fetched from Cache Reserve to respond to a miss in the edge cache.

#### Purge

Asset purges are free operations.

Cache Reserve will be instantly purged along with edge cache when you send a purge by URL request. Refer to [cache configurations](https://developers.cloudflare.com/cache/how-to/purge-cache/) for details.

Other purge methods, such as purge by tag, host, prefix, or purge everything will force an attempt to [revalidate](https://developers.cloudflare.com/cache/concepts/cache-responses/#revalidated) on the subsequent request for the Cache Reserve asset. Note that assets purged this way will still incur storage costs until their retention TTL expires.

Note

Note this differs from the standard CDN's purge by tag, host, or prefix features which force a cache miss, requiring the origin to deliver the asset in full.

## Cache Reserve billing examples

#### Example 1

Assuming 1,000 assets (each 1 GB) are written to Cache Reserve at the start of the month and each asset is read 1,000 times, the estimated cost for the month would be:

| Usage              | Billable Quantity                         | Price           |        |
| ------------------ | ----------------------------------------- | --------------- | ------ |
| Class B Operations | (1,000 assets) \* (1,000 reads per asset) | 1,000,000       | $0.36  |
| Class A Operations | (1,000 assets) \* (1 write per asset)     | 1,000           | $4.50  |
| Storage            | (1,000 assets) \* (1GB per asset)         | 1,000 GB-months | $15.00 |
| **TOTAL**          | **$19.86**                                |                 |        |

Note

The billable quantity is rounded up to the nearest million.

#### Example 2

Assuming 1,000,000 assets (each 1 MB) are in Cache Reserve, and:

* each asset expires and is rewritten into Cache Reserve 1 time per day
* each asset is read 2 times per day

the estimated cost for the month would be:

| Usage              | Billable Quantity                                    | Price           |         |
| ------------------ | ---------------------------------------------------- | --------------- | ------- |
| Class B Operations | (1,000,000 assets) \* (2 reads per day) \* (30 days) | 60,000,000      | $21.60  |
| Class A Operations | (1,000,000 assets) \* (1 write per day) \* (30 days) | 30,000,000      | $135.00 |
| Storage            | (1,000,000 assets) \* (1MB per asset)                | 1,000 GB-months | $15.00  |
| **TOTAL**          | **$171.60**                                          |                 |         |

Note

The billable quantity is rounded up to the nearest million.

## Tips and best practices

Cache Reserve is designed for use with [Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) enabled for maximum origin shielding. Using Cache Reserve without Tiered Cache may result in higher storage operation costs. The Cloudflare dashboard will warn you if you try to enable Cache Reserve without Tiered Cache.

## Cache Reserve Analytics

Cache Reserve Analytics provides insights regarding your Cache Reserve usage. It allows you to check what content is stored in Cache Reserve, how often it is being accessed, how long it has been there and how much egress from your origin it is saving you.

In the **Overview** section, under **Cache Reserve**, you have access to the following metrics:

* **Egress savings (bandwidth)** \- is an estimation based on response bytes served from Cache Reserve that did not need to be served from your origin server. These are represented as cache hits.
* **Requests served by Cache Reserve** \- is the number of requests served by Cache Reserve (total).
* **Data storage summary** \- is based on a representative sample of requests. Refer to [Sampling](https://developers.cloudflare.com/analytics/graphql-api/sampling/) for more details about how Cloudflare samples data.  
   * **Current data stored** \- is the data stored (currently) over time.  
   * **Aggregate storage usage** \- is the total of storage used for the selected timestamp.
* **Operations** \- Class A (writes) and Class B (reads) operations over time.

## Cache Reserve clear button

You can remove all data stored in Cache Reserve through the dashboard or via API. To clear your cache reserve:

* Cache Reserve must have already been enabled for the zone.
* Cache Reserve needs to be off.

Be aware that the deletion may take up to 24 hours to complete.

* [ Dashboard ](#tab-panel-6817)
* [ API ](#tab-panel-6818)

1. In the Cloudflare dashboard, go to the **Cache Reserve** page.  
[ Go to **Cache Reserve** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/cache-reserve)
2. In **Delete Cache Reserve Data**, select **Delete Storage**.

To delete Cache Reserve data via API use the following example requests. For more information, refer to the [API documentation](https://developers.cloudflare.com/api/resources/cache/subresources/cache%5Freserve/methods/clear/).

**Request 1: Get Cache Reserve status**

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`
* `Zone Settings Read`
* `Zone Read`
* `Zone Write`

Get Cache Reserve setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/cache/cache_reserve" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

Response

```

{

  "result": {

    "editable": true,

    "id": "cache_reserve",

    "value": "off"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

If Cache Reserve is turned off, you can proceed to the Cache Reserve Clear operation.

**Request 2: Start Cache Reserve Clear**

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`
* `Zone Write`

Start Cache Reserve Clear

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/cache/cache_reserve_clear" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

Response

```

{

  "result": {

    "id": "cache_reserve_clear",

    "start_ts": "2024-06-02T10:00:00.12345Z",

    "state": "In-progress"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/advanced-configuration/","name":"Advanced configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/advanced-configuration/cache-reserve/","name":"Cache Reserve"}}]}
```

---

---
title: Crawler Hints
description: Signal search engine crawlers when content changes with IndexNow.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Crawler Hints

Crawler Hints uses Cloudflare cache signals to tell search engines when your content has likely changed, so they crawl your site at the right time instead of guessing.

## Background

Search engines and similar services operate massive networks of bots that crawl the Internet to identify the content most relevant to a user query. Content on the web is always changing though, and search engine crawlers must continually wander the Internet and guess how frequently they should check a site for content updates.

With Crawler Hints, Cloudflare can proactively tell a crawler about the best time to index or when content changes. Additionally, Crawler Hints supports [IndexNow ↗](https://www.indexnow.org/), which allows websites to notify search engines whenever content on their website content is created, updated, or deleted. Crawler Hints uses cache-status [MISS](https://developers.cloudflare.com/cache/concepts/cache-responses/#miss) to determine when content has likely been updated and sends it to IndexNow's crawler. If an asset's response has an HTTP status code greater than 4xx, the Crawler hints will not report that to [IndexNow ↗](https://www.indexnow.org/).

## Benefits

Crawler Hints help search engines and other bot-powered services serve the freshest version of your content, which can improve search rankings.

Crawler Hints also reduces unnecessary crawl traffic to your origin, lowering resource consumption and improving site performance.

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

## Enable Crawler Hints

1. In the Cloudflare dashboard, go to the **Configuration** page.  
[ Go to **Configuration** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/configuration)
2. Enable **Crawler Hints**.

After enabling Crawler Hints, Cloudflare will begin sending hints to search engines about when they should crawl particular parts of your website.

## Prevent indexing for a specific page

When enabled, Crawler Hints is a global setting for your entire website. You can stop a specific page from being indexed by either:

* Having the origin server send through the header `X-Robots-Tag: noindex` on any pages that should not be indexed.
* Including `<meta name="robots" content="noindex, nofollow" />` in the HTML of any pages that should not be indexed.
* Creating a [Response header Transform Rule](https://developers.cloudflare.com/rules/transform/response-header-modification/) in Cloudflare to add the `X-Robots-Tag: noindex` header instead of doing it from the origin server.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/advanced-configuration/","name":"Advanced configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/advanced-configuration/crawler-hints/","name":"Crawler Hints"}}]}
```

---

---
title: Early Hints
description: Preload assets with 103 Early Hints to speed up page loads.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Early Hints

When a browser requests a page, the origin server takes time to prepare the full response. Early Hints uses this wait time to send the browser a preliminary `103` response containing `Link` headers that tell the browser which assets it will need. The browser can start loading those assets before the full response arrives, which speeds up page loads.

Early Hints is defined in [RFC 8297 ↗](https://httpwg.org/specs/rfc8297.html) as a new HTTP status code (`103 Early Hints`). Cloudflare caches and serves these `103` responses with `Link` headers from your HTML pages, reducing user-perceived latency.

Note

Early Hints is currently only supported over HTTP/2 and HTTP/3.

For more information about Early Hints, refer to the [Cloudflare ↗](https://blog.cloudflare.com/early-hints) and [Google Chrome ↗](https://developer.chrome.com/en/blog/early-hints/) blogs.

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

## Enable Early Hints

1. In the Cloudflare dashboard, go to the **Speed** \> **Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/speed/optimization)
2. Go to the **Content Optimization** tab.
3. For **Early Hints**, toggle the switch to **On**.

## Generate Early Hints

Early Hints are only generated and cached:

* For URIs with `.html`, `.htm`, or `.php` file extensions, or no file extension
* On 200, 301, or 302 response return codes
* When the response contains [link headers ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Link) with preconnect or preload rel types, such as `Link: </img/preloaded.png>; rel=preload`

Note

Early Hints cache entries are keyed by request URI and ignore query strings.

## Emit Early Hints

Cloudflare will asynchronously look up and emit a cached 103 Early Hints response ahead of a main response.

Currently, only certain browser versions will take action to preload or preconnect on receiving Early Hints, such as Google Chrome M94 and higher. Instructions for running WebPageTest to experiment with compatible client browsers can be found in the [blog post ↗](https://blog.cloudflare.com/early-hints/#testing-early-hints-with-web-page-test).

Additionally, keep the following in mind:

* Early Hints responses may be emitted before reaching the origin server or Worker. When Early Hints is enabled and pages on your site require authentication, unauthenticated visitors may receive a 103 response. The 103 response would contain cached Link headers and be sent before a 403 Forbidden response from your origin.
* Early Hints may be emitted less frequently on requests where the content is cacheable. Cloudflare CDN is more likely to retrieve a response header before the asynchronous Early Hints lookup finishes if the response has been cached. Cloudflare will not send a 103 response if the main response header is already available.
* Cloudflare currently disables Early Hints on some User-Agents, for example, select search crawler bots that show incompatibility with 1xx responses.
* You may see an influx of `504` responses with the `RequestSource` of `earlyHintsCache` in Cloudflare Logs when Early Hints is enabled, which is expected and benign. Requests from `earlyHintsCache` are internal subrequests for cached Early Hints, and they are neither end user requests, nor do they go to your origin. Their response status only indicates whether there are cached Early Hints for the request URI (`200` on cache HIT, `504` on cache MISS). These requests are already filtered out in other views, such as Cache Analytics. To filter out these requests or to filter requests by end users of your website only, please refer to [Filter end users](https://developers.cloudflare.com/analytics/graphql-api/features/filtering/#filter-end-users).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/advanced-configuration/","name":"Advanced configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/advanced-configuration/early-hints/","name":"Early Hints"}}]}
```

---

---
title: Query String Sort
description: Improve cache hit rates by sorting query string parameters.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Query String Sort

**Query String Sort** increases cache-hit rates by first sorting query strings into a consistent order before checking the Cloudflare cache.

By default, Cloudflare’s cache treats resources as distinct if their URL query strings are in a different order. For instance, these resources are cached separately:

* `/video/48088296?title=0&byline=0&portrait=0&color=51a516`
* `/video/48088296?byline=0&color=51a516&portrait=0&title=0`

Query String Sort changes this behavior. If two query strings exist with the same name, the URL is sorted by the parameter value. For example:

`/example/file?word=alpha&word=beta` and `/example/file?word=beta&word=alpha`

would be sorted to:

`/example/file?word=alpha&word=beta`

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | No  | No       | No         | Yes |

---

## Enable Query String Sort

To enable Query String Sort:

1. Log into the [Cloudflare dashboard ↗](https://dash.cloudflare.com).
2. Select your account and zone.
3. Go to **Caching** \> **Configuration**.
4. For **Enable Query String Sort**, switch the toggle to **On**.

---

## Unexpected behavior with WordPress admin pages

When a site or an application requires exact query string ordering, enabling Query String Sort might cause unexpected behavior.

For example in the WordPress admin UI, you might notice any of the following behaviors:

* No media appear in the Media Library
* Inability to customize the site via **Appearance** \> **Customize**
* Inability to drag any widget to a sidebar in **Appearance** \> **Widgets**
* Inability to edit menus in **Appearance** \> **Menus**

To understand why this happens, note that WordPress [concatenates JavaScript files ↗](https://developer.wordpress.org/advanced-administration/wordpress/wp-config/#disable-javascript-concatenation) to speed up the administration interface. The way WordPress implements this involves multiple occurrences of `load[]` parameters in the query string, where the order of those parameters is crucial.

Note

Note that more recent versions of WordPress may not experience this issue, as a patch has been implemented in WordPress since 2019\. The patch can be found at [WordPress Core Trac Changeset 45456 ↗](https://core.trac.wordpress.org/changeset/45456).

### Identify the problem

The screenshot below shows an example where resources in the Media Library are not rendered correctly and the browser debugging console reveals that the page is throwing an error:

![Resources in the Media Library are not rendered correctly](https://developers.cloudflare.com/_astro/media_library_enabling_query.Cf3Ny9Zt_1hN0m2.webp) 

When the page `load-scripts.php` loads, the browser sends a request to Cloudflare for:

```

/wp-admin/load-scripts.php?c=0&load%5B%5D=hoverIntent,common,admin-bar,underscore,shortcode,backbone,wp-util,wp-backbone,media-models,wp-plupload,wp-mediaelement,wp-api-r&load%5B%5D=equest,media-views,media-editor,media-audiovideo,mce-view,imgareaselect,image-edit,media-grid,media,svg-painter&ver=5.0.3


```

With Query String Sort enabled, Cloudflare will then sort the parameters and values in the request query string, resulting in the following:

```

/wp-admin/load-scripts.php?c=0&load%5B%5D=equest,media-views,media-editor,media-audiovideo,mce-view,imgareaselect,image-edit,media-grid,media,svg-painter&load%5B%5D=hoverIntent,common,admin-bar,underscore,shortcode,backbone,wp-util,wp-backbone,media-models,wp-plupload,wp-mediaelement,wp-api-r&ver=5.0.3


```

Note that the `load[]` parameters were swapped, as `equest` should come before `hoverIntent` when alphabetically ordered.

When this happens, you will most likely find errors in the browser console, such as:

`_____ is not defined at load-scripts.php?c=0&load[]=...`

This type of error indicates that Query String Sort is inadvertently breaking some WordPress admin page functionality.

After sorting, the query then goes to Cloudflare's cache infrastructure (and to the origin server, if the resource is not in the Cloudflare cache or is not cacheable). The origin server then serves the concatenated scripts, which are ordered differently. Because scripts might depend on other scripts, this process might break dependencies.

### Respond to the issue

Start by analyzing your site or application behavior around the use of query strings. Do you have assets served with multiple possible arrangements of query strings?

For example, you might have an image resizing endpoint or a search form, where the order of query parameters might vary - such as width, height, and version - yet a unique parameter combination points to a single relevant asset.

To minimize problems, consider:

* Disabling **Query String Sort** for the site if you’re sure that this feature does not add value to any part of your site. Cloudflare disables this option by default in the **Caching** app.
* Use Cache Rules to enable **Query String Sort** (set **Cache key** \> **Sort query string**: `On`) for URLs where preserving the query string parameter order is not important.
* Alternatively, use Cache Rules to disable **Query String Sort** for URLs where a specific parameter order is required. For example, set **Cache key** \> **Sort query string**: `Off` for URI paths starting with `/wp-admin/load-scripts.php`, or for any URLs with similar requirements.

To learn more about Cache Rules, visit [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/).

---

## Related resources

* [Increasing Cache Hit Rates with Query String Sort ↗](https://blog.cloudflare.com/increasing-cache-hit-rates-with-query-string-sort/)
* [Best Practice: Caching Everything While Ignoring Query Strings](https://developers.cloudflare.com/cache/how-to/cache-rules/examples/cache-everything-ignore-query-strings/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/advanced-configuration/","name":"Advanced configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/advanced-configuration/query-string-sort/","name":"Query String Sort"}}]}
```

---

---
title: Serving tailored content with Cloudflare
description: Serve different cached content based on device type, location, or language.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Serving tailored content with Cloudflare

Content negotiation is the practice of serving different versions of a resource from a single URL, tailoring the experience to the end user. Common examples include delivering content in a specific language (`Accept-Language`), optimizing for a device (`User-Agent`), or serving modern image formats (`Accept`).

Cloudflare's global network is designed to handle this at scale. For common scenarios such as serving next-generation images, this negotiation is streamlined with a dedicated feature. For more customized logic, Cloudflare provides a toolkit including Transform Rules, Snippets, Custom Cache Keys, and Workers, giving you granular control to ensure the right content is served to every user, every time.

---

## Use query strings

The [Transform Rule](https://developers.cloudflare.com/rules/transform/) method is ideal when you can create a distinct URL, such as serving content based on a visitor's location.

### Geolocation example

In this example, you run an e-commerce site and want to display prices in the local currency based on the visitor's country.

1. In the Cloudflare dashboard, go to the Rules **Overview** page.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/rules/overview)
2. Select **Create rule** and select the option **URL Rewrite Rule**.
3. Enter a descriptive name, such as `Vary by Country - Canada`.
4. In **If incoming requests match...**, select **Custom filter expression**.
5. Under **When incoming requests match...**, create the following expression:  
   * **Field:** `Country`  
   * **Operator:** `equals`  
   * **Value:** `Canada`
6. Under **Then...**  
   * for **Path**, select **Preserve**.  
   * for **Query**, select **Rewrite to**: **Dynamic** `loc=ca`
7. Select **Save**.

Now, requests from Canada to `/products/item` will be transformed to `/products/item?loc=ca` before reaching your origin or the cache, creating a distinct cache entry.

Availability

Free, Pro, Business, and Enterprise plans

---

## Vary for Images

[Vary for Images](https://developers.cloudflare.com/cache/advanced-configuration/vary-for-images/) tells Cloudflare which variants your origin supports. Cloudflare then caches each version separately and serves the correct one to browsers without contacting your origin each time. This feature is managed via the Cloudflare API.

### Enable Vary for Images

To enable this feature, create a _variants rule_ using the API. This rule maps file extensions to the image formats your origin can serve.

For example, the following API call tells Cloudflare that for `.jpeg` and `.jpg` files, your origin can serve `image/webp` and `image/avif` variants:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`
* `Zone Write`

Change variants setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/cache/variants" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": {

        "jpeg": [

            "image/webp",

            "image/avif"

        ],

        "jpg": [

            "image/webp",

            "image/avif"

        ]

    }

  }'


```

After creating the rule, Cloudflare will create distinct cache entries for each image variant, improving performance for users with modern browsers.

Availability

Pro, Business, and Enterprise plans

## Use Snippets for programmatic caching

[Snippets](https://developers.cloudflare.com/rules/snippets/) are self-contained JavaScript fetch handlers that run at the edge on your requests through Cloudflare. They allow you to programmatically interact with the cache, providing full control over the cache key and response behavior without changing the user-facing URL.

### Example: A/B testing

In this example, you run an A/B test controlled by a cookie named `ab-test` (with values `group-a` or `group-b`). You want to cache a different version of the page for each group.

1. In the Cloudflare dashboard, go to the **Snippets** page.  
[ Go to **Snippets** ](https://dash.cloudflare.com/?to=/:account/:zone/rules/snippets)
2. Select **Create new Snippet** and name it `ab-test-caching`.
3. Paste the following code. It modifies the cache key based on the `ab-test` cookie and caches the response for 30 days.

JavaScript

```

const CACHE_DURATION = 30 * 24 * 60 * 60; // 30 days


export default {

  async fetch(request) {

    // Construct a new URL for the cache key based on the A/B cookie

    const abCookie = request.headers.get('Cookie')?.match(/ab-test=([^;]+)/)?.[1] || 'control';

    const url = new URL(request.url);

    url.pathname = `/ab-test/${abCookie}${url.pathname}`;


    const cacheKey = new Request(url, request);

    const cache = caches.default;


    let response = await cache.match(cacheKey);

    if (!response) {

      // If not in cache, fetch from origin

      response = await fetch(request);

      response = new Response(response.body, response);

      response.headers.set("Cache-Control", `s-maxage=${CACHE_DURATION}`);

      // Put the response into cache with the custom key

      await cache.put(cacheKey, response.clone());

    }

    return response;

  },

};


```

1. Save and deploy the Snippet.
2. From the Snippets dashboard, select **Attach to routes** to assign the Snippet.

Availability

Pro, Business, and Enterprise plans

## Custom Cache Keys (Enterprise)

If your account is on an Enterprise plan, the [Custom Cache Keys](https://developers.cloudflare.com/cache/how-to/cache-keys) feature provides a no-code interface to define which request properties are included in the cache key.

Custom Cache Key options:

* Cache by device type
* Query string option `No query string parameters except`
* Include headers and values
* Include cookie names and values
* User: Device type, Country, Language

### Example: Same URL, different content

If your origin serves different content types (for example, `application/json` vs. `text/html`) at the same URL based on the `Accept` header, use a custom cache key to cache them separately.

1. In the Cloudflare dashboard, go to the **Cache Rules** page.  
[ Go to **Cache Rules** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/cache-rules)
2. Select **Create rule**.
3. Enter rule name, such as `Vary by Accept Header`.
4. Set the condition for the rule to apply (for example, a specific hostname or path).
5. Under **Cache key**, select **Use custom key**.
6. Select **Add new**.  
   * **Type**: `Header`  
   * **Name**: `Accept`  
   * **Value**: Add each `value`, or leave empty for all.
7. Select **Deploy**.

This configuration creates separate cache entries based on the `Accept` header value, respecting your API's content negotiation.

Availability

Enterprise plans only

## Use Cloudflare Workers for advanced logic

For complex caching scenarios, [Cloudflare Workers](https://developers.cloudflare.com/cache/interaction-cloudflare-products/workers/) provide a full serverless environment ideal for custom logic at scale.

### Example: Device type – Free/Pro/Biz (without Tiered Cache)

This Worker detects whether a visitor is on a mobile or desktop device and creates separate cache entries for each, ensuring the correct version of the site is served and cached.

JavaScript

```

export default {

  async fetch(request, env, ctx) {

    const userAgent = request.headers.get('User-Agent') || '';

    const deviceType = userAgent.includes('Mobile') ? 'mobile' : 'desktop';


    // Create a new URL for the cache key that includes the device type

    const url = new URL(request.url);

    url.pathname = `/${deviceType}${url.pathname}`;


    const cacheKey = new Request(url, request);

    const cache = caches.default;


    let response = await cache.match(cacheKey);


    if (!response) {

      console.log(`Cache miss for ${deviceType} device. Fetching from origin.`);

      response = await fetch(request);

      let responseToCache = response.clone();

      ctx.waitUntil(cache.put(cacheKey, responseToCache));

    }


    return response;

  },

};


```

Availability

Free and Paid plans

### Example: Device type – Enterprise (with Tiered Cache)

This Worker detects if a visitor is on a mobile device or a desktop and creates a separate cache entry for each, ensuring the correct version of the site is served and cached. Uses the Enterprise `cf.customCacheKey` feature.

JavaScript

```

export default {

  async fetch(request) {

    // 1. Determine the device type from the User-Agent header

    const userAgent = request.headers.get('User-Agent') || '';

    const deviceType = userAgent.includes('Mobile') ? 'mobile' : 'desktop';


    // 2. Create a custom cache key by appending the device type to the URL

    const customCacheKey = `${request.url}-${deviceType}`;


    // 3. Fetch the response. Cloudflare's cache automatically uses the

    //    customCacheKey for cache operations (match, put).

    const response = await fetch(request, {

      cf: {

        cacheKey: customCacheKey,

      },

    });


    // Optionally, you can modify the response before returning it

    // For example, add a header to indicate which cache key was used

    const newResponse = new Response(response.body, response);

    newResponse.headers.set("X-Cache-Key", customCacheKey);

    return newResponse;

  },

};


```

Availability

Enterprise only

## Example: Caching Next.js RSC payloads

A common challenge is caching content from frameworks like Next.js, which uses an `RSC` (React Server Components) request header to differentiate between HTML page loads and RSC data payloads for the same URL. Here are the best ways to handle this.

### Method 1: Transform Rules

The simplest solution is to create a [Transform Rule](https://developers.cloudflare.com/rules/transform/) that checks for the `RSC` header and adds a unique query parameter on the request, creating two distinct cacheable URLs: `/page` (for HTML) and `/page?_rsc=1` (for the RSC payload).

1. In the Cloudflare dashboard, go to the Rules **Overview** page.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/rules/overview)
2. Select **Create rule** and select the option **URL Rewrite Rule**.
3. Enter a name, such as `Vary by RSC Header`.
4. In **If incoming requests match**, select **Custom filter expression**.
5. Under **When incoming requests match**, manually edit the expression so that it checks for the presence of the `RSC` header:  
   * `has_key(http.request.headers, "rsc")`
6. Under **Then**:  
   * For **Path**, select **Preserve**.  
   * For **Query**, select **Rewrite to**, select **Static**: `_rsc=1`.
7. Select **Save**.

### Method 2: Snippets or Custom Cache Keys

Alternatively, use [Snippets](https://developers.cloudflare.com/rules/snippets/) or [Custom Cache Keys](https://developers.cloudflare.com/cache/how-to/cache-keys) to add the `RSC` header directly to the cache key without modifying the visible URL. This provides a cleaner URL but requires more advanced configuration.

Availability

* Snippets: Pro, Business, Enterprise
* Custom Cache Keys: Enterprise only

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/advanced-configuration/","name":"Advanced configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/advanced-configuration/serve-tailored-content/","name":"Serving tailored content with Cloudflare"}}]}
```

---

---
title: Vary for images
description: Serve images in the best format for each visitor browser.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Vary for images

The `Vary` HTTP response header tells Cloudflare that an origin can serve different versions of the same resource depending on the request headers. For images, this allows your origin to serve modern formats like WebP or AVIF to browsers that support them, while continuing to serve JPEG or PNG to others.

When Cloudflare receives a response with image variants, it caches each variant separately. Subsequent requests from browsers with the same image format preferences are served directly from cache without contacting your origin.

Vary for Images works by parsing the `Accept` header in each request to determine which image format the browser supports, then serving the matching cached variant.

Vary for images is available for Pro, Business, and Enterprise customers.

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | No  | Yes      | Yes        | Yes |

## File extensions

You can use vary for images on the file extensions below if the origin server sends the `Vary: Accept` response header. If the origin server sends `Vary: Accept` but does not serve the set variant, the response is not cached and displays `BYPASS` in the cache status in the response header. Additionally, the list of variant types the origin serves for each extension must be configured so that Cloudflare decides which variant to serve without contacting the origin server.

File extensions enabled for varying

* .avif
* .bmp
* .gif
* .jpg
* .jpeg
* .jp2
* .png
* .tif
* .tiff
* .webp

## Enable vary for images

Vary for Images is enabled through Cloudflare's API by creating a variants rule. In the examples below, learn how to serve JPEG, WebP, and AVIF variants for `.jpeg` and `.jpg` extensions.

### Create a variants rule

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`
* `Zone Write`

Change variants setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/cache/variants" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": {

        "jpeg": [

            "image/webp",

            "image/avif"

        ],

        "jpg": [

            "image/webp",

            "image/avif"

        ]

    }

  }'


```

### Modify to only allow WebP variants

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`
* `Zone Write`

Change variants setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/cache/variants" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": {

        "jpeg": [

            "image/webp"

        ],

        "jpg": [

            "image/webp"

        ]

    }

  }'


```

### Delete the rule

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`
* `Zone Write`

Delete variants setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/cache/variants" \

  --request DELETE \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

### Get the rule

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`
* `Zone Settings Read`
* `Zone Read`
* `Zone Write`

Get variants setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/cache/variants" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

To learn more about purging varied images, refer to [Purge varied images](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-varied-images/).

## Limitations

* For Vary for images to work, your image URLs must include the file extension in the path and not the query string. For example the URL `https://example.com/image.jpg` is compatible but `https://example.com/index.php?file=image.jpg` is not compatible.
* Your origin must return an image type matching the file extension in the URL when a HTTP client sends no `Accept` header, or an `Accept: */*` header. Otherwise, you will see `CF-Cache-Status: BYPASS` in the HTTP response headers.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/advanced-configuration/","name":"Advanced configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/advanced-configuration/vary-for-images/","name":"Vary for images"}}]}
```

---

---
title: Avoid web cache poisoning
description: Protect your site from web cache poisoning attacks.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Avoid web cache poisoning

A cache poisoning attack uses an HTTP request to trick an origin web server into responding with a harmful resource that has the same cache key as a clean request. As a result, the poisoned resource gets cached and served to other users.

A Content Delivery Network (CDN) like Cloudflare relies on cache keys to compare new requests against cached resources. The CDN then determines whether the resource should be served from the cache or requested directly from the origin web server.

## Learn about Cache Poisoning

To deepen your understanding of the risks and vulnerabilities associated with cache poisoning, consult the following resources:

* [Practical Web Cache Poisoning ↗](https://portswigger.net/blog/practical-web-cache-poisoning)
* [How Cloudflare protects customers from cache poisoning ↗](https://blog.cloudflare.com/cache-poisoning-protection/)

## Only cache files that are truly static

Review the caching configuration for your origin web server and ensure you are caching files that are static and do not depend on user input in any way. To learn more about Cloudflare caching, review:

* [Which file extensions does Cloudflare cache for static content?](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/)
* [How Do I Tell Cloudflare What to Cache?](https://developers.cloudflare.com/cache/how-to/cache-rules/)

## Do not trust data in HTTP headers

Attackers can exploit HTTP headers to inject malicious content into cached responses. For example, if your application reflects an untrusted header value in the response body, an attacker could use this to perform cross-site scripting (XSS) through the cache. To reduce this risk:

* Do not rely on values in HTTP headers if they are not part of your [cache key](https://developers.cloudflare.com/cache/how-to/cache-keys/).
* Do not include untrusted header values in your response body.

## Do not trust GET request bodies

Cloudflare caches contents of GET request bodies, but they are not included in the cache key. GET request bodies should be considered untrusted and should not modify the contents of a response. If a GET body can change the contents of a response, consider bypassing cache or using a POST request.

## Monitor web security advisories

To keep informed about Internet security threats, Cloudflare recommends that you monitor web security advisories on a regular basis. Some of the more popular advisories include:

* [Drupal Security Advisories ↗](https://www.drupal.org/security)
* [Symfony Security Advisories ↗](https://symfony.com/blog/category/security-advisories)
* [Laminas Security Advisories ↗](https://getlaminas.org/security/advisories)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/cache-security/","name":"Cache security"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/cache-security/avoid-web-poisoning/","name":"Avoid web cache poisoning"}}]}
```

---

---
title: Cache Deception Armor
description: Prevent cache deception attacks that expose private content.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache Deception Armor

## Web Cache Deception attacks

A Web Cache Deception attack tricks a user into visiting a URL that appears to point to a static asset but actually returns dynamic, personalized content from the origin.

This attack works when an origin treats requests to non-existent paths as equivalent to a parent path — for example, when `http://www.example.com/newsfeed` is a dynamic page that returns different content for each authenticated user, and the origin also serves that same response for `/newsfeed/foo.jpg`. Because the path ends in `.jpg`, Cloudflare caches the response by default. The attacker then visits the same URL and receives the cached copy of the user's personalized content.

## Cache Deception Armor protects against attacks

You can protect users from Web Cache Deception attacks by [creating a cache rule](https://developers.cloudflare.com/cache/cache-security/cache-deception-armor/#enable-cache-deception-armor). With this rule, you can continue to cache static assets, but the rule will verify a URL's extension matches the returned `Content-Type`.

In the newsfeed example above, if `http://www.example.com/newsfeed` is a script that outputs a webpage, the `Content-Type` is `text/html`. On the other hand, `http://www.example.com/newsfeed/foo.jpg` is expected to have `image/jpeg` as `Content-Type`. When a mismatch that could result in a Web Cache Deception attack is found, Cloudflare does not cache the response.

### Exceptions

* If the returned `Content-Type` is `application/octet-stream`, the extension does not matter because that is typically a signal to instruct the browser to save the asset instead of to display it.
* Cloudflare allows `.jpg` to be served as `image/webp` or `.gif` as `video/webm` and other cases that are unlikely to be attacks.
* Keep in mind that Cache Deception Armor depends upon [Origin Cache Control](https://developers.cloudflare.com/cache/concepts/cache-control/). A `Cache-Control` header from the origin, or an [Edge Cache TTL Cache Rule](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#edge-ttl) may override the protection.

## Enable Cache Deception Armor

To enable Cache Deception Armor, you need to start by creating a [cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/). Follow the steps below for guidance:

1. In the Cloudflare dashboard, go to the **Cache Rules** page.  
[ Go to **Cache Rules** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/cache-rules)
2. Select **Create rule**.
3. Under **When incoming requests match**, define the [rule expression](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/edit-expressions/#expression-builder).
4. Under **Then**, in the **Cache eligibility** section, select **Eligible for cache**.
5. Add the **Cache Key** setting to the rule and turn on **Cache deception armor**.
6. To save and deploy your rule, select **Deploy**. If you are not ready to deploy your rule, select **Save as Draft**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/cache-security/","name":"Cache security"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/cache-security/cache-deception-armor/","name":"Cache Deception Armor"}}]}
```

---

---
title: Cross-Origin Resource Sharing (CORS)
description: How Cloudflare handles CORS headers and cross-origin resource caching.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cross-Origin Resource Sharing (CORS)

A cross-origin request occurs when a webpage on one origin (for example, `a.example.com`) requests a resource from a different origin (for example, `b.secondexample.com`). Cross-Origin Resource Sharing (CORS) is a mechanism that uses HTTP headers to let the server at `b.secondexample.com` indicate whether `a.example.com` is allowed to access its resources. Browsers enforce these headers and block access to responses that are not permitted.

Cloudflare supports CORS by:

* Identifying cached assets based on the `Host` Header, `Origin` Header, URL path, and query. This allows different resources to use the same `Host` header but different `Origin` headers.
* Passing `Access-Control-Allow-Origin` headers from the origin server to the browser.

The `Access-Control-Allow-Origin` header lets a server specify rules for sharing its resources with external origins. A server may respond with different `Access-Control-Allow-Origin` values depending on the `Origin` header in the request. These headers are often present on [cacheable content](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/).

## Add or change CORS headers at the origin server

If you add or change CORS configuration at your origin web server, purging the Cloudflare cache by URL does not update the CORS headers. Force Cloudflare to retrieve the new CORS headers via one of the following options:

* Change the filename or URL to bypass cache to instruct Cloudflare to retrieve the latest CORS headers.
* Use the [single-file purge API](https://developers.cloudflare.com/api/resources/cache/methods/purge/#purge-cached-content-by-url) to specify the appropriate CORS headers along with the purge request.
* Update the resource’s last-modified time at your origin web server. Then, complete a [full purge](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-everything/) to retrieve the latest version of your assets including updated CORS headers.

## Add or change CORS headers on Cloudflare

You can use one of following methods to set CORS headers using Cloudflare products:

* Use a [Worker](https://developers.cloudflare.com/workers/): Refer to [CORS header proxy](https://developers.cloudflare.com/workers/examples/cors-header-proxy/) for an example.
* Configure a [Snippet](https://developers.cloudflare.com/rules/snippets/): Refer to [Define CORS headers](https://developers.cloudflare.com/rules/snippets/examples/define-cors-headers/) for an example.
* Use [Transform Rules](https://developers.cloudflare.com/rules/transform/): Refer to [Add a wildcard CORS response header](https://developers.cloudflare.com/rules/transform/examples/add-cors-header/) for an example.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/cache-security/","name":"Cache security"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/cache-security/cors/","name":"Cross-Origin Resource Sharing (CORS)"}}]}
```

---

---
title: Head Requests and Set-Cookie Headers
description: How Cloudflare handles HEAD requests and Set-Cookie headers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Head Requests and Set-Cookie Headers

This page describes how Cloudflare's cache system behaves in interaction with:

* `HEAD` requests
* `Set-Cookie` response headers

## Interaction of `HEAD` requests with Cache

Cloudflare converts `HEAD` requests to `GET` requests for [cacheable requests](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#default-cached-file-extensions).

When you make a `HEAD` request for a cacheable resource and Cloudflare does not have that resource in the edge cache, a cache miss happens. Cloudflare will send a `GET` request to your origin, cache the full response and return the response headers only. Make sure the origin server is set up to handle `GET` requests, even if only `HEAD` requests are expected, so that compatibility with this behavior is ensured.

## Interaction of `Set-Cookie` response header with Cache

For non-cacheable requests, `Set-Cookie` is always preserved. For cacheable requests, there are three possible behaviors:

* `Set-Cookie` is returned from origin and the default cache level is used. If [origin cache control](https://developers.cloudflare.com/cache/concepts/cache-control/) is not enabled, Cloudflare removes the `Set-Cookie` and caches the asset. If origin cache control is enabled, Cloudflare does not cache the asset and preserves the `Set-Cookie`. A cache status of `BYPASS` is returned.
* `Set-Cookie` is returned from origin and the cache level is set to `Cache Everything` in Page Rules, or `Eligible for cache` in Cache Rules. In this case, Cloudflare preserves the `Set-Cookie` but does not cache the asset. A cache `MISS` will be returned every time.
* `Set-Cookie` is returned from origin, the cache level is set to `Cache Everything` in Page Rules, or `Eligible for cache` in Cache Rules, and edge cache TTL is explicitly set using either the "Ignore cache-control header and use this TTL" or "Status code TTL" setting. In this case, Cloudflare removes the `Set-Cookie` and the asset is cached.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/concepts/cache-behavior/","name":"Head Requests and Set-Cookie Headers"}}]}
```

---

---
title: Origin Cache Control
description: How origin Cache-Control headers affect Cloudflare caching behavior.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Origin Cache Control

Origin Cache Control is a Cloudflare feature. When enabled on an Enterprise customer's website, it indicates that Cloudflare should strictly respect `Cache-Control` directives received from the origin server. Free, Pro and Business customers have this feature enabled by default.

`Cache-Control` directives in the HTTP response from your origin server provide specific [caching instructions ↗](https://datatracker.ietf.org/doc/html/rfc7234) to intermediary services like Cloudflare.

With the Origin Cache Control feature enabled, `Cache-Control` directives present in the origin server's response will be followed as specified. For example, if the response includes a `max-age` directive of 3,600 seconds, Cloudflare will cache the resource for that duration before checking the origin server again for updates.

Cloudflare's [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/) allows users to either augment or override an origin server's `Cache-Control` headers or [default policies](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/) set by Cloudflare.

The following sections cover:

* The most common `Cache-Control` directives.
* How to enable Origin Cache Control.
* How Origin Cache Control behaves with `Cache-Control` directives.
* How other Cloudflare products interact with `Cache-Control` directives.

## `Cache-control` directives

A `Cache-Control` header can include a number of directives, and the directive dictates who can cache a resource along with how long those resources can be cached before they must be updated.

Note

For more information about `Cache-Control` directives at origin servers, refer to the [Mozilla Cache-Control documentation ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control).

If multiple directives are passed together, each directive is separated by a comma. If the directive takes an argument, it follows the directive separated by an equal sign. For example: `max-age=86400`.

Directives can be broken down into four groups: [cacheability](https://developers.cloudflare.com/cache/concepts/cache-control/#cacheability), [expiration](https://developers.cloudflare.com/cache/concepts/cache-control/#expiration), [revalidation](https://developers.cloudflare.com/cache/concepts/cache-control/#revalidation), and [other](https://developers.cloudflare.com/cache/concepts/cache-control/#other).

### Cacheability

Cacheability refers to whether or not a resource should enter a cache, and the directives below indicate a resource's cacheability.

* `public` — Indicates any cache may store the response, even if the response is normally non-cacheable or cacheable only within a private cache.
* `private` — Indicates the response message is intended for a single user, such as a browser cache, and must not be stored by a shared cache like Cloudflare or a corporate proxy.
* `no-store` — Indicates any cache, such as a client or proxy cache, must not store any part of either the immediate request or response.

### Expiration

Expiration refers to how long a resource should remain in the cache, and the directives below affect how long a resource stays in the cache.

Note

Cloudflare respects whichever value is higher: the [Browser Cache TTL](https://developers.cloudflare.com/cache/how-to/edge-browser-cache-ttl/) in Cloudflare or the `max-age` header. You can also simultaneously specify a Cloudflare Edge Cache TTL different than a Browser's Cache TTL respectively via the `s-maxage` and `max-age` `Cache-Control` headers.

When using Origin Cache Control and setting `max-age=0`, Cloudflare prefers to cache and revalidate. With Origin Cache Control off and `max-age=0`, Cloudflare will bypass cache.

When setting `no-cache` with Origin Cache Control off, Cloudflare does not cache. When setting `no-cache` with Origin Cache Control on, Cloudflare caches and always revalidates.

* `max-age=seconds` — Indicates the response is stale after its age is greater than the specified number of seconds. Age is defined as the time in seconds since the asset was served from the origin server. The `seconds` argument is an unquoted integer.
* `s-maxage=seconds` — Indicates that in shared caches, the maximum age specified by this directive overrides the maximum age specified by either the `max-age` directive or the `Expires` header field. The `s-maxage` directive also implies the semantics of the `proxy-revalidate` response directive. Browsers ignore `s-maxage`.

`s-maxage` disables `stale-while-revalidate`

Per [RFC 9111 ↗](https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.2.10-4), `s-maxage` incorporates the semantics of `proxy-revalidate`, which means a shared cache must not serve stale content without first revalidating with the origin. For a complete list of directives that disable `stale-while-revalidate` and workarounds, refer to [Controlling stale behavior](https://developers.cloudflare.com/cache/concepts/revalidation/#controlling-stale-behavior).

* `no-cache` — Indicates the response cannot be used to satisfy a subsequent request without successful validation on the origin server. This allows an origin server to prevent a cache from using the origin to satisfy a request without contacting it, even by caches that have been configured to send stale responses.

Ensure the HTTP `Expires` header is set in your origin server to use Greenwich Mean Time (GMT) as stipulated in [RFC 2616 ↗](https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 "3.3.1 Full Date").

### Revalidation

Revalidation determines how the cache should behave when a resource expires, and the directives below affect the revalidation behavior.

* `must-revalidate` — Indicates that once the resource is stale, a cache (client or proxy) must not use the response to satisfy subsequent requests without successful validation on the origin server.
* `proxy-revalidate` — Has the same meaning as the `must-revalidate` response directive except that it does not apply to private client caches.
* `stale-while-revalidate=<seconds>` — When present in an HTTP response, indicates caches may serve the response in which it appears after it becomes stale, up to the indicated number of seconds since the resource expired. If [Always Online](https://developers.cloudflare.com/cache/how-to/always-online/) is enabled, then the `stale-while-revalidate` and `stale-if-error` directives are ignored. This directive is not supported when using the Cache API methods `cache.match` or `cache.put`. For more information, refer to the [Workers documentation for Cache API](https://developers.cloudflare.com/workers/runtime-apis/cache/#methods).

Note

`stale-while-revalidate` is now fully asynchronous. The first request after expiry triggers revalidation in the background and immediately receives stale content with an UPDATING status instead of blocking. All requests during revalidation are served stale with an UPDATING status until the origin responds, after which they receive a HIT.

For more details, refer to [Revalidation](https://developers.cloudflare.com/cache/concepts/revalidation/#asynchronous-revalidation).

* `stale-if-error=<seconds>` — Indicates that when an error is encountered, a cached stale response may be used to satisfy the request, regardless of other freshness information. To avoid this behavior, include `stale-if-error=0` directive with the object returned from the origin. This directive is not supported when using the Cache API methods `cache.match` or `cache.put`. For more information, refer to the [Workers documentation for Cache API](https://developers.cloudflare.com/workers/runtime-apis/cache/#methods).

The `stale-if-error` directive is ignored if [Always Online](https://developers.cloudflare.com/cache/how-to/always-online/) is enabled or if an explicit in-protocol directive is passed. Examples of explicit in-protocol directives include a `no-store` or `no-cache cache` directive, a `must-revalidate` cache-response-directive, or an applicable `s-maxage` or `proxy-revalidate` cache-response-directive.

### Other

Additional directives that influence cache behavior are listed below.

* `no-transform` — Indicates that an intermediary — regardless of whether it implements a cache — must not transform the payload.
* `vary` — Cloudflare does not consider vary values in caching decisions. Nevertheless, vary values are respected when [Vary for images](https://developers.cloudflare.com/cache/advanced-configuration/vary-for-images/) is configured and when the vary header is [vary: accept-encoding](https://developers.cloudflare.com/speed/optimization/content/compression/).
* `immutable` — Indicates to clients the response body does not change over time. The resource, if unexpired, is unchanged on the server. The user should not send a conditional revalidation request, such as `If-None-Match` or `If-Modified-Since`, to check for updates, even when the user explicitly refreshes the page. This directive has no effect on public caches like Cloudflare, but does change browser behavior.

### Understand `no-store` and `no-cache` directives

There is often confusion between the directives `Cache-Control: no-store` and `Cache-Control: no-cache`, particularly regarding how they impact browser caching and features like the [Back-Forward Cache ↗](https://developer.mozilla.org/en-US/docs/Glossary/bfcache) (BFCache).

#### `no-store`

* Tells both browsers and intermediaries (like CDNs) not to store a copy of the response under any circumstance.
* The response is never written to disk or memory, which means the browser must fetch it again every time.
* In many browsers, `no-store` disables BFCache, because restoring a page from BFCache requires the browser to keep a copy of the page's memory state, which contradicts the “do not store” directive.
* This directive is used for highly sensitive or dynamic data (for example, banking apps, personal information, secure dashboards).

#### `no-cache`

* Allows storing of the response (in both browser and intermediate caches), but requires revalidation with the origin server before using it.
* This ensures the content is always up-to-date, while still potentially allowing BFCache or other forms of performance optimization.
* This directive is used for data that changes frequently but is not sensitive, and can be served faster if validated rather than re-downloaded.

For more information about how these directives behave when Origin Cache Control is enabled or disabled refer to the [Directives](https://developers.cloudflare.com/cache/concepts/cache-control/#directives) section.

## Enable Origin Cache Control

If you enable Origin Cache Control, Cloudflare will aim to strictly adhere to [RFC 7234 ↗](https://datatracker.ietf.org/doc/html/rfc7234). Enterprise customers have the ability to select if Cloudflare will adhere to this behavior, enabling or disabling Origin Cache Control for their websites through cache rules in the [dashboard](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#origin-cache-control-enterprise-only) or via [API](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#origin-cache-control-enterprise-only). Free, Pro, and Business customers have this option enabled by default and cannot disable it.

## Origin Cache Control behavior

The following section covers the directives and behavioral conditions associated with enabling or disabling Origin Cache Control.

### Directives

The table below lists directives and their behaviors when Origin Cache Control is disabled and when it is enabled.

| Directive               | Origin Cache Control Disabled Behavior          | Origin Cache Control Enabled Behavior                                                                                                        |
| ----------------------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| s-maxage=0              | Will not cache.                                 | Caches and always revalidates                                                                                                                |
| max-age=0               | Will not cache.                                 | Caches and always revalidates.                                                                                                               |
| no-cache                | Will not cache.                                 | Caches and always revalidates. Does not serve stale.                                                                                         |
| no-cache=<headers>      | Will not cache.                                 | Caches if headers mentioned in no-cache=<headers> do not exist. Always revalidates if any header mentioned in no-cache=<headers> is present. |
| Private=<headers>       | Will not cache.                                 | Does not cache <headers> values mentioned in Private=<headers> directive.                                                                    |
| must-revalidate         | Cache directive is ignored and stale is served. | Does not serve stale. Must revalidate for CDN and for browser.                                                                               |
| proxy-revalidate        | Cache directive is ignored and stale is served. | Does not serve stale. Must revalidate for CDN but not for browser.                                                                           |
| no-transform            | May (un)Gzip, Polish, email filter, etc.        | Does not transform body.                                                                                                                     |
| s-maxage=delta, delta>1 | Same as max-age.                                | Max-age and proxy-revalidate.                                                                                                                |
| immutable               | Not proxied downstream.                         | Proxied downstream. Browser facing, does not impact caching proxies.                                                                         |
| no-store                | Will not cache.                                 | Will not cache.                                                                                                                              |

### Conditions

Certain scenarios also affect Origin Cache Control behavior when it is enabled or disabled.

| Condition                                                              | Origin Cache Control disabled behavior                      | Origin Cache Control enabled behavior                        | |  Presence of Authorization header. | Content may be cached. | Content is cached only if must-revalidate, public, or s-maxage is also present. |
| ---------------------------------------------------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------ | ---------------------- | ------------------------------------------------------------------------------- |
| Use of no-cache header.                                                | In logs, cacheStatus=miss.                                  | In logs, cacheStatus=bypass.                                 |                                      |                        |                                                                                 |
| Origin response has Set-Cookie header and default cache level is used. | Content may be cached with stripped set-cookie header.      | Content is not cached.                                       |                                      |                        |                                                                                 |
| Browser Cache TTL is set.                                              | Cache-Control returned to eyeball does not include private. | If origin returns private in Cache-Control then preserve it. |                                      |                        |                                                                                 |

Note

When the `Cloudflare-Cdn-Cache-Control` header is set, OCC is turned **on** (regardless of whether OCC is enabled or disabled). As a result, we apply our Authorization header logic (per [RFC 7234, Section 3.2 ↗](https://tools.ietf.org/html/rfc7234#section-3.2)) to allow only the `s-maxage`, `must-revalidate`, or `public` directives. If any other directive is present, we do not cache the asset and instead return `BYPASS`.

## Examples

Review the examples below to learn which directives to use with the `Cache-Control` header to control specific caching behavior.

Cache a static asset.

`Cache-Control: public, max-age=86400`

Ensure a secret asset is never cached.

`Cache-Control: no-store`

Cache assets on browsers but not on proxy cache.

`Cache-Control: private, max-age=3600`

Cache assets in client and proxy caches, but prefer revalidation when serve.

`Cache-Control: public, no-cache`

Cache assets in proxy caches but REQUIRE revalidation by the proxy when serve.

`Cache-Control: public, no-cache, proxy-revalidate` or `Cache-Control: public, s-maxage=0`

Cache assets in proxy caches, but REQUIRE revalidation by any cache when serve.

`Cache-Control: public, no-cache, must-revalidate`

Cache assets, but ensure the proxy does not modify it.

`Cache-Control: public, no-transform`

This configuration also disables transformation like gzip or brotli compression from our edge to your visitors if the original payload was served uncompressed.

Cache assets with revalidation, but allow stale responses if origin server is unreachable.

`Cache-Control: public, max-age=3600, stale-if-error=60`

With this configuration, Cloudflare attempts to revalidate the content with the origin server after it has been in cache for 3600 seconds (one hour). If the server returns an error instead of proper revalidation responses, Cloudflare continues serving the stale resource for a total of one minute beyond the expiration of the resource.

Cache assets for different amounts of time on Cloudflare and in visitor browsers.

`Cache-Control: public, max-age=7200, s-maxage=3600`

Cache an asset and serve while asset is being revalidated.

`Cache-Control: max-age=600, stale-while-revalidate=30`

This configuration indicates the asset is fresh for 600 seconds. The asset can be served stale for up to an additional 30 seconds while Cloudflare revalidates the asset with the origin in the background. For more information, refer to [Revalidation](https://developers.cloudflare.com/cache/concepts/revalidation/).

Note

Do not use `s-maxage` with `stale-while-revalidate`. The `s-maxage` directive implies `proxy-revalidate`, which prevents shared caches from serving stale content. For workarounds, refer to [Controlling stale behavior](https://developers.cloudflare.com/cache/concepts/revalidation/#controlling-stale-behavior).

## Interaction with other Cloudflare features

This section covers how other Cloudflare features interact with `Cache-Control` directives.

### Edge Cache TTL

[Edge Cache TTL](https://developers.cloudflare.com/cache/how-to/edge-browser-cache-ttl/#edge-cache-ttl) Cache Rules override `s-maxage` and disable revalidation directives if present. When Origin Cache Control is enabled at Cloudflare, the original `Cache-Control` header passes downstream from our edge even if Edge Cache TTL overrides are present. Otherwise, when Origin Cache Control is disabled at Cloudflare, Cloudflare overrides the Origin Cache Control.

### Browser Cache TTL

[Browser Cache TTL](https://developers.cloudflare.com/cache/how-to/edge-browser-cache-ttl/#browser-cache-ttl) Cache Rules override `max-age` settings passed downstream from our edge, typically to your visitor's browsers.

### Polish

[Polish](https://developers.cloudflare.com/images/polish/) is disabled when the `no-transform` directive is present.

### Gzip and Other Compression

Compression is disabled when the `no-transform` directive is present. If the original asset fetched from the origin is compressed, it is served compressed to the visitor. If the original asset is uncompressed, compression is not applied.

### JavaScript Detections

[JavaScript Detections](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/javascript-detections/) injection is disabled when the `no-transform` directive is present. The `cf.bot_management.js_detection.passed` field will show as `missing` for affected requests.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/concepts/cache-control/","name":"Origin Cache Control"}}]}
```

---

---
title: Cloudflare cache responses
description: Cache status headers returned by Cloudflare in HTTP responses.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare cache responses

The `CF-Cache-Status` header output indicates whether a resource is cached or not. To investigate cache responses returned by this header, use services like [Redbot ↗](https://redbot.org/), [webpagetest.org ↗](http://www.webpagetest.org/), or a visual tool like [Cloudflare Optics plugin ↗](https://chromewebstore.google.com/detail/cloudflare-optics/mdjgbjnbdnhneejmmaabmccfehigbjbe).

`Age` response header

The `Age` response header is a header returned from cache that specifies the time in seconds that an asset has been in Cloudflare's cache. This value resets if the asset is revalidated, purged, or evicted and then re-cached.

The `Age` header is only present for responses served from the cache. It will not appear on a cache MISS, dynamic traffic, the first request that populates the lower tier HIT from tiered cache `CacheTieredFill=true` or any responses that did not originate from the cache (for example, responses generated by a Worker that bypassed the cache).

Below you can find a comprehensive breakdown of Cloudflare's cache response statuses.

## HIT

The resource was found in Cloudflare's cache.

## MISS

The resource was not found in Cloudflare's cache and was served from the origin web server.

## NONE/UNKNOWN

Cloudflare generated a response that denotes the asset is not eligible for caching. This may have happened because:

* A Worker generated a response without sending any subrequests. In this case, the response did not come from cache, so the cache status will be `none/unknown`.
* A Worker request made a subrequest (`fetch`). In this case, the subrequest will be logged with a cache status, while the main request will be logged with `none/unknown` status (the main request did not hit cache, since Workers sits in front of cache).
* A WAF custom rule was triggered to block a request. The response will come from the Cloudflare global network before it hits cache. Since there is no cache status, Cloudflare will log as `none/unknown`.
* A [redirect rule](https://developers.cloudflare.com/rules/url-forwarding/) or [Always Use HTTPS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/) caused the global network to respond with a redirect to another asset/URL. This redirect response happens before the request reaches cache, so the cache status is `none/unknown`.

## EXPIRED

The resource was found in Cloudflare's cache but was expired and served from the origin web server.

## STALE

The resource was served from Cloudflare's cache but was expired. Cloudflare could not contact the origin web server to retrieve an updated resource.

## BYPASS

The origin web server instructed Cloudflare to bypass cache via a `Cache-Control` header set to `no-cache`, `private`, or `max-age=0` even though Cloudflare originally preferred to cache the asset. BYPASS is returned when enabling [Origin Cache-Control](https://developers.cloudflare.com/cache/concepts/cache-control/). Cloudflare also sets BYPASS when your origin web server sends cookies in the response header. If the Request to your origin web server includes an `Authorization` header, in some cases the response will also be BYPASS. Refer to [Conditions](https://developers.cloudflare.com/cache/concepts/cache-control/#conditions) in the Origin Cache-Control behavior section for more details.

## REVALIDATED

The origin confirmed the cached resource was unchanged via a conditional request (`If-Modified-Since` or `If-None-Match`), and the response is served from Cloudflare's cache. This status reflects the synchronous validation path — the request waits for the origin to respond before being served.

With [asynchronous stale-while-revalidate](https://developers.cloudflare.com/cache/concepts/revalidation/#asynchronous-revalidation), most revalidations now return `UPDATING` or `HIT` instead. `REVALIDATED` is seen in the following situations: `stale-while-revalidate` is not set; directives like `must-revalidate` or `no-cache` (with [Origin Cache Control](https://developers.cloudflare.com/cache/concepts/cache-control/) enabled) prevent stale content from being served; or the zone is an Enterprise zone that has not yet been migrated (refer to [Synchronous revalidation](https://developers.cloudflare.com/cache/concepts/revalidation/#synchronous-revalidation-legacy)).

## UPDATING

The resource was expired but served from Cloudflare's cache while the origin updates it in the background. `UPDATING` is the expected status during [asynchronous stale-while-revalidate](https://developers.cloudflare.com/cache/concepts/revalidation/#asynchronous-revalidation) revalidation — all requests during the revalidation window receive `UPDATING` or `HIT` rather than waiting for the origin.

## DYNAMIC

Cloudflare does not consider the asset eligible to cache and your Cloudflare settings do not explicitly instruct Cloudflare to cache the asset. Instead, the asset was requested from the origin web server. Use [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/) to implement custom caching options.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/concepts/cache-responses/","name":"Cloudflare cache responses"}}]}
```

---

---
title: CDN-Cache-Control
description: Use CDN-Cache-Control headers to control Cloudflare cache independently.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# CDN-Cache-Control

`CDN-Cache-Control` is a response header field set on the origin to separately control the behavior of CDN caches from other intermediaries that might handle a response. You can set the `CDN-Cache-Control` or `Cloudflare-CDN-Cache-Control` response header using the same directives used with the [Cache-Control](https://developers.cloudflare.com/cache/concepts/cache-control/).

## Header precedence

You have several options available to determine how `CDN-Cache-Control` directives interact with `Cache-Control` directives.

If a [Cache Response Rule](https://developers.cloudflare.com/cache/how-to/cache-response-rules/) sets `Cache-Control` directives using the `set_cache_control` action, those directives take precedence over any origin-set `Cloudflare-CDN-Cache-Control` and `CDN-Cache-Control` headers.

When no Cache Response Rule applies, an origin can:

* Return the `CDN-Cache-Control` response header which Cloudflare evaluates to make caching decisions. `Cache-Control`, if also returned by the origin, is proxied as is and does not affect caching decisions made by Cloudflare. Additionally, `CDN-Cache-Control` is proxied downstream in case there are other CDNs between Cloudflare and the browser.
* Return the `Cloudflare-CDN-Cache-Control` response header. This results in the same behavior as the origin returning `CDN-Cache-Control` except Cloudflare does not proxy `Cloudflare-CDN-Cache-Control` downstream because it’s a header only used to control Cloudflare. This option is beneficial if you want only Cloudflare to have a different caching behavior while all other downstream servers rely on `Cache-Control` or if you do not want Cloudflare to proxy the `CDN-Cache-Control` header downstream.
* Return both `Cloudflare-CDN-Cache-Control` and `CDN-Cache-Control` response headers. In this case, Cloudflare only looks at `Cloudflare-CDN-Cache-Control` when making caching decisions because it is the most specific version of `CDN-Cache-Control` and proxies `CDN-Cache-Control` downstream. Only forwarding `CDN-Cache-Control` in this situation is beneficial if you want Cloudflare to have a different caching behavior than other CDNs downstream.

Additionally, surrogates will not honor `Cache-Control` headers in the response from an origin. For example, if the `Surrogate-Control` header is present within the response, Cloudflare ignores any `Cache-Control` directives, even if the `Surrogate-Control` header does not contain directives.

## Interaction with other Cloudflare features

### Edge Cache TTL cache rule

The [Edge Cache TTL cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#edge-ttl) overrides the amount of time an asset is cached on the edge (Cloudflare data centers). This cache rule overrides directives in `Cloudflare-CDN-Cache-Control/CDN-Cache-Control` which manage how long an asset is cached on the edge. You can create this rule in the dashboard in **Caching** \> **Cache Rules**.

### Browser Cache TTL cache rule

The [Browser Cache TTL cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#browser-ttl) overrides the amount of time an asset is cached by browsers/servers downstream of Cloudflare. Browser Cache TTL only modifies the `Cache-Control` response header. This cache rule does not modify `Cloudflare-CDN-Cache-Control/CDN-Cache-Control` response headers.

### Other Origin Response Headers

The origin returns the `Expires` response header which specifies the amount of time before an object is considered stale to the browser. This response header does not affect the caching decision at Cloudflare when `Cloudflare-CDN-Cache-Control/CDN-Cache-Control` is in use.

### Cloudflare Default cache values

In situations where Cloudflare does not receive `Cloudflare-CDN-Cache-Control`, `CDN-Cache-Control`, or `Cache-Control` values, cacheable assets use the general [default values](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/).

## When to use CDN-Cache-Control

### Manage cached assets TTLs

Use `CDN-Cache-Control` when you want to manage cached asset’s TTLs separately for origin caches, CDN caches, and browser caches. The example below shows how you can manage your cached asset’s TTLs using origin-set response headers.

Headers:

* `Cache-Control: max-age=14400, s-maxage=84000`
* `Cloudflare-CDN-Cache-Control: max-age=24400`
* `CDN-Cache-Control: max-age=18000`

Cache behavior:

| Caches               | Cache TTL (seconds) | |  Origin Server Cache | 14400 |
| -------------------- | ------------------- | ---------------------- | ----- |
| Network Shared Cache | 84000               |                        |       |
| Cloudflare Edge      | 24400               |                        |       |
| Other CDNs           | 18000               |                        |       |
| Browser Cache        | 14400               |                        |       |

### Specify when to serve stale content

Use `CDN-Cache-Control` headers in conjunction with `Cache-Control` headers to specify when to serve stale content in the case of error or during revalidation. The example below shows how you might set your headers and directives to apply to CDNs when handling errors.

Headers:

* `Cache-Control: stale-if-error=400`
* `Cloudflare-CDN-Cache-Control: stale-if-error=60`
* `CDN-Cache-Control: stale-if-error=200`

Behavior in response to [5XX error](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/):

| Caches          | Stale served (seconds) in response to error | |  Origin Cache Layer/Network Cache/Browser Cache | 400 (if it assumes the directive applies) |
| --------------- | ------------------------------------------- | ------------------------------------------------- | ----------------------------------------- |
| Cloudflare Edge | 60                                          |                                                   |                                           |
| Other CDN       | 200                                         |                                                   |                                           |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/concepts/cdn-cache-control/","name":"CDN-Cache-Control"}}]}
```

---

---
title: Customize cache
description: Methods for customizing cache behavior with rules, Workers, and headers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Customize cache

Some possible combinations of origin web server settings and Cloudflare [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/) include:

## Create a directory for static content at your origin web server

For example, create a `/static/` subdirectory at your origin web server and a Cache Everything Cache Rule matching the following expression:

* Using the Expression Builder: `Hostname contains "example.com" AND URI Path starts with "/static"`
* Using the Expression Editor: `(http.host contains "example.com" and starts_with(http.request.uri.path, "/static"))`

## Append a unique file extension to static pages

For example, create a `.shtml` file extension for resources at your origin web server and a Cache Everything Cache Rule matching the following expression:

* Using the Expression Builder: `Hostname contains "example.com" AND URI Path ends with ".shtml"`
* Using the Expression Editor: `(http.host contains "example.com" and ends_with(http.request.uri.path, ".shtml"))`

## Add a query string to a resource’s URL to mark the content as static

For example, add a `static=true` query string for resources at your origin web server and a Cache Everything Cache Rule matching the following expression:

* Using the Expression Builder: `Hostname contains "example.com" AND URI Query String contains "static=true"`
* Using the Expression Editor: `(http.host contains "example.com" and http.request.uri.query contains "static=true")`

Resources that match a Cache Everything Cache Rule are still not cached if the origin web server sends a Cache-Control header of `max-age=0`, `private`, `no-cache`, or an `Expires` header with an already expired date. Include the [Edge Cache TTL](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#edge-ttl) setting within the Cache Everything Cache Rule to additionally override the `Cache-Control` headers from the origin web server.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/concepts/customize-cache/","name":"Customize cache"}}]}
```

---

---
title: Default cache behavior
description: Default file extensions and content types that Cloudflare caches.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Default cache behavior

Cloudflare respects the origin web server’s cache headers in the following order unless an [Edge Cache TTL cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#edge-ttl) overrides the headers. Refer to the [Edge TTL](https://developers.cloudflare.com/cache/how-to/configure-cache-status-code/#edge-ttl) section for details on default TTL behavior.

* Cloudflare **does not** cache the resource when:  
   * The `Cache-Control` header is set to `private`, `no-store`, `no-cache`, or `max-age=0`.  
   * The [Set-Cookie header](https://developers.cloudflare.com/cache/concepts/cache-behavior/#interaction-of-set-cookie-response-header-with-cache) exists.  
   * The HTTP request method is anything other than a `GET`.
* Cloudflare **does** cache the resource when:  
   * The `Cache-Control` header is set to `public` and `max-age` is greater than 0.  
   * The `Expires` header is set to a future date.

Note

Cloudflare does cache the resource even if there is no `Cache-Control` header based on [status codes](https://developers.cloudflare.com/cache/how-to/configure-cache-status-code/#edge-ttl).

Note

If both `max-age` and an `Expires` header are set, `max-age` will be used by Cloudflare.

When [Origin Cache Control](https://developers.cloudflare.com/cache/concepts/cache-control/) is enabled on an Enterprise customer’s website, it indicates that Cloudflare should strictly respect `Cache-Control` directives received from the origin server. Free, Pro and Business customers have this feature enabled by default. For a list of directives and behaviors when Origin Cache-Control is enabled or disabled, refer to [Cache-Control directives](https://developers.cloudflare.com/cache/concepts/cache-control/#cache-control-directives).

## Client side range requests

Clients can send range requests to be served from the cache using the `Range` header. Note that:

* If the origin response includes a `Content-Length` header, then the specified byte range will be returned with an [HTTP 206](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/2xx-success/#206-partial-content) response.
* If the origin response does not include the `Content-Length` header, the cache will return the full content with an HTTP 200 response.

## Request collapsing

When multiple requests arrive simultaneously at a single Cloudflare data center for the same asset that is not in cache (a cache miss), Cloudflare uses a cache lock to avoid sending duplicate requests to your origin. Only the first request is forwarded to the origin to fetch the asset. The remaining requests wait for the first request to complete, after which the response is [streamed ↗](https://blog.cloudflare.com/introducing-concurrent-streaming-acceleration/) to all waiting requests.

The cache lock ensures that Cloudflare only sends one request at a time to the origin for a given asset from a single location in Cloudflare's network, preventing the origin from receiving excessive traffic.

## Default cached file extensions

Cloudflare only caches based on file extension and not by MIME type. The Cloudflare CDN does not cache HTML or JSON by default. Additionally, by default Cloudflare caches a website's robots.txt.

| 7Z    | CSV  | GIF  | MIDI | PNG  | TIF   | ZIP |
| ----- | ---- | ---- | ---- | ---- | ----- | --- |
| AVI   | DOC  | GZ   | MKV  | PPT  | TIFF  | ZST |
| AVIF  | DOCX | ICO  | MP3  | PPTX | TTF   |     |
| APK   | DMG  | ISO  | MP4  | PS   | WEBM  |     |
| BIN   | EJS  | JAR  | OGG  | RAR  | WEBP  |     |
| BMP   | EOT  | JPG  | OTF  | SVG  | WOFF  |     |
| BZ2   | EPS  | JPEG | PDF  | SVGZ | WOFF2 |     |
| CLASS | EXE  | JS   | PICT | SWF  | XLS   |     |
| CSS   | FLAC | MID  | PLS  | TAR  | XLSX  |     |

To cache additional content, refer to [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/) to create a rule to cache everything.

## Edge TTL

By default, Cloudflare caches certain HTTP response codes with the following Edge Cache TTL when a `cache-control` directive or `expires` response header are not present.

| HTTP status code | Default TTL |
| ---------------- | ----------- |
| 200, 206, 301    | 120m        |
| 302, 303         | 20m         |
| 404, 410         | 3m          |

All other status codes are not cached by default.

## Customization options and limits

Cloudflare’s CDN provides several cache customization options:

* Caching behavior for individual URLs via [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/)
[ Go to **Cache Rules** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/cache-rules) 
* Customize caching with [Cloudflare Workers](https://developers.cloudflare.com/workers/reference/how-the-cache-works/)
* Adjust caching level, cache TTL, and more in the Caching page in the Cloudflare dashboard:
[ Go to **Configuration** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/configuration) 

### Upload limits

| Free            | Pro    | Business | Enterprise |         |
| --------------- | ------ | -------- | ---------- | ------- |
| Availability    | Yes    | Yes      | Yes        | Yes     |
| Max upload size | 100 MB | 100 MB   | 200 MB     | 500+ MB |

Customers can reduce the **Maximum Upload Size** from the zone's **Network** page.

If you require a larger upload, you can group requests into smaller chunks, upload the full resource through a [DNS-only (unproxied) DNS record](https://developers.cloudflare.com/dns/proxy-status/) or [upgrade your plan](https://developers.cloudflare.com/billing/manage/change-plan/).

### Cacheable size limits

Cloudflare cacheable file limits:

* Free, Pro and Business customers have a limit of 512 MB.
* For Enterprise customers the default maximum cacheable file size is 5 GB. Contact your account team to request a limit increase.

## When does Cloudflare cache successfully?

The connection status between visitors and Cloudflare can vary, affecting whether Cloudflare caches the content or not. If Cloudflare has already established a connection to the origin and started fetching the content, it will continue to retrieve and cache the entire content, even if the visitor disconnects midway. However, if a visitor disconnects before the origin responds to Cloudflare's request, no content will have been fetched yet, so Cloudflare will not start caching the content.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/concepts/default-cache-behavior/","name":"Default cache behavior"}}]}
```

---

---
title: Retention vs Freshness (TTL)
description: How cache retention and TTL freshness differ in Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Retention vs Freshness (TTL)

In the context of Cloudflare CDN (Content Delivery Network), retention and freshness refer to two separate but related concepts. For an object in cache, freshness is how long it should be considered valid without consulting its source, while retention refers to how long it stays in cache before being removed.

## Retention

When a resource is requested, Cloudflare caches it so that subsequent requests can be served without contacting the origin server. If a cached object is not requested again, it is eventually removed to make room for newer, more popular content. This removal process is called eviction.

Cloudflare uses a Least Recently Used (LRU) algorithm to decide which objects to evict when the cache is full. An object's retention period is how long it stays in cache before being evicted. Retention is determined by the object's relative popularity and the size of the cache, and is not configurable.

## Freshness (TTL)

Freshness, also known as Time to Live (TTL), determines how long a cache can use an object without checking with the origin again. For example, if an object has a TTL of five minutes, the cache serves it directly for five minutes after first receiving it. After five minutes, Cloudflare must check with the origin to confirm the object is still valid before serving it again. There are a few ways to configure TTLs for resources served through Cloudflare's CDN:

* Include [Origin Cache Control](https://developers.cloudflare.com/cache/concepts/cache-control/) or [CDN Cache Control](https://developers.cloudflare.com/cache/concepts/cache-control/) directives, like `max-age` or `s-maxage`, in the origin cache-control response header.
* Use [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/) or [Workers](https://developers.cloudflare.com/cache/interaction-cloudflare-products/workers/).

If an object in cache is no longer fresh, Cloudflare revalidates it with the origin. When [stale-while-revalidate](https://developers.cloudflare.com/cache/concepts/cache-control/#revalidation) is set, revalidation happens asynchronously at expiry — visitors continue to be served from cache while Cloudflare fetches a fresh copy in the background. Without this directive, incoming requests wait for the origin to respond before receiving content. The origin can either confirm the cached object is still valid (refreshing its TTL) or return a new version to replace it. Refer to [Revalidation](https://developers.cloudflare.com/cache/concepts/revalidation/) for details.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/concepts/retention-vs-freshness/","name":"Retention vs Freshness (TTL)"}}]}
```

---

---
title: Revalidation
description: How Cloudflare revalidates stale cached content with your origin.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Revalidation

## Stale-while-revalidate

When a cached asset expires, Cloudflare uses the [stale-while-revalidate](https://developers.cloudflare.com/cache/concepts/cache-control/#revalidation) directive in `Cache-Control` to determine whether it can continue serving the stale asset while fetching a fresh copy from the origin. If the directive is present and the asset is within the allowed staleness window, Cloudflare serves the expired content to visitors and revalidates in the background. By using headers like `If-Modified-Since` and `ETag`, Cloudflare validates content without fully re-fetching it, reducing origin traffic.

Note

Asynchronous `stale-while-revalidate` is live for all Free, Pro, and Business zones. Enterprise zones are actively being migrated. The previous synchronous behavior is described in [Synchronous revalidation](#synchronous-revalidation-legacy).

## Asynchronous revalidation

Revalidation is fully asynchronous. When a cached asset expires and `stale-while-revalidate` is set, the first request that arrives after expiry triggers revalidation in the background. That request immediately receives stale content with an [UPDATING](https://developers.cloudflare.com/cache/concepts/cache-responses/#updating) status instead of blocking until the origin responds. All following requests also receive stale content with an `UPDATING` status until the origin responds. Once revalidation completes, subsequent requests receive fresh content with a [HIT](https://developers.cloudflare.com/cache/concepts/cache-responses/#hit) status.

If the stale content is still valid, Cloudflare sets a new TTL. If the content has changed, the origin provides fresh content to replace the old.

## Synchronous revalidation (legacy)

Note

Synchronous revalidation refers to a previous implementation that is only available to a subset of Enterprise zones that have not been migrated yet. All other zones use [asynchronous revalidation](#asynchronous-revalidation).

With synchronous revalidation (a legacy implementation), `stale-while-revalidate` blocks on the first request that arrives after a cached asset expired. That first request is held until the origin responds, and is served with a [MISS](https://developers.cloudflare.com/cache/concepts/cache-responses/#miss) or [REVALIDATED](https://developers.cloudflare.com/cache/concepts/cache-responses/#revalidated) status. Any other requests that arrive during this time for the same asset in the same cache location are served stale with the [UPDATING](https://developers.cloudflare.com/cache/concepts/cache-responses/#updating) status.

For example, if 1,000 requests arrive simultaneously for an expired asset in this previous implementation, one request goes to the origin while the other 999 are served stale from cache. The first visitor experiences higher latency because they have to wait for the origin round-trip.

On the other hand, with [asynchronous revalidation](#asynchronous-revalidation) all 1,000 requests are served from cache immediately and no visitor is blocked.

## Controlling stale behavior

Cloudflare only serves stale content during revalidation if your origin includes the `stale-while-revalidate` directive in its `Cache-Control` header. Without this directive, visitors wait for the origin to respond before receiving content.

If your origin sets `stale-while-revalidate` but you want to override it, you can disable stale serving through the [Serve stale content while revalidating](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#serve-stale-content-while-revalidating) setting in Cache Rules.

### Directives that disable stale-while-revalidate

When [Origin Cache Control](https://developers.cloudflare.com/cache/concepts/cache-control/#enable-origin-cache-control) is enabled, the following `Cache-Control` directives prevent Cloudflare from serving stale content, per [RFC 9111 §4.2.4 ↗](https://www.rfc-editor.org/rfc/rfc9111.html#section-4.2.4):

* **`must-revalidate`** — Prohibits serving stale content; the cache must revalidate with the origin first.
* **`proxy-revalidate`** — Same as `must-revalidate`, but only applies to shared caches (like Cloudflare).
* **`s-maxage`** — Implies `proxy-revalidate` semantics, so shared caches cannot serve stale content.
* **`no-cache`** — Requires revalidation before serving any cached response.

If any of these directives are present alongside `stale-while-revalidate`, Cloudflare will not serve stale content — requests will return `EXPIRED` instead of `UPDATING`.

Workaround for different edge and browser TTLs

If you need `stale-while-revalidate` behavior with a different TTL for Cloudflare than for browsers, do not use `s-maxage`. Instead, configure your origin to send `max-age` with `stale-while-revalidate`, then use [Edge Cache TTL](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#edge-ttl) in Cache Rules to set a separate TTL for Cloudflare.

For all available directives or behavior when Origin Cache Control is disabled, refer to [Cache-Control directives](https://developers.cloudflare.com/cache/concepts/cache-control/#cache-control-directives).

## Smart revalidation towards users

When both [Last-Modified ↗](https://datatracker.ietf.org/doc/html/rfc7232?cf%5Fhistory%5Fstate=%7B%22guid%22%3A%22C255D9FF78CD46CDA4F76812EA68C350%22%2C%22historyId%22%3A15%2C%22targetId%22%3A%226C8153BAEF7BC0C5A331E28F8BCF1ABA%22%7D#section-2.2) and [Etag ↗](https://datatracker.ietf.org/doc/html/rfc7232?cf%5Fhistory%5Fstate=%7B%22guid%22%3A%22C255D9FF78CD46CDA4F76812EA68C350%22%2C%22historyId%22%3A13%2C%22targetId%22%3A%226C8153BAEF7BC0C5A331E28F8BCF1ABA%22%7D#section-2.3) headers are absent from the origin server response, Smart Edge Revalidation will use the time the object was cached on Cloudflare's global network as the `Last-Modified` header value. When a browser sends a revalidation request to Cloudflare using `If-Modified-Since` or `If-None-Match`, our global network can answer those revalidation questions using the `Last-Modified` header generated from Smart Edge Revalidation. In this way, our global network can ensure efficient revalidation even if the headers are not sent from the origin.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/concepts/revalidation/","name":"Revalidation"}}]}
```

---

---
title: Glossary
description: Definitions for terms used across Cloudflare Cache documentation.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Glossary

Review the definitions for terms used across Cloudflare's Cache documentation.

| Term                                                     | Definition                                                                                                                                                                                                                                                                                                           |
| -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cache                                                    | A temporary storage area where frequently accessed data is stored for quick retrieval.                                                                                                                                                                                                                               |
| cache hit                                                | When a requested piece of content is found in the cache, reducing the need to fetch it from the origin server.                                                                                                                                                                                                       |
| cache lock                                               | Cache lock (or mutex) is a mechanism employed by CDN data centers, comprising numerous servers, to prevent the overloading of origin servers. This mechanism ensures that only one server can request a specific file from the origin at any given time, facilitating efficient coordination among the servers.      |
| cache miss                                               | When a requested piece of content is not found in the cache, requiring the server to fetch it from the origin server.                                                                                                                                                                                                |
| cached bandwidth (cached egress bandwidth)               | The amount of bandwidth served from Cloudflare without hitting the origin server. Cached bandwidth is the sum of all EdgeResponseBytes where CacheCacheStatus equals hit, stale, updating, ignored, or revalidated.                                                                                                  |
| cached requests                                          | The number of requests served from Cloudflare without having to hit the origin server. Cached requests are the sum of all requests where CacheCacheStatus equals hit, stale, updating, ignored. This does not include revalidated since the request had to be sent to the origin server.                             |
| caching                                                  | The process of storing copies of files or data in a cache to accelerate future requests.                                                                                                                                                                                                                             |
| dynamic content                                          | Dynamic content refers to website content that changes based on factors specific to the user such as time of visit, location, and device. News websites or social media are examples of this type of content. For this type of website, content has to be fetched from the origin server every time it is requested. |
| edge server                                              | A server located at the edge of a network, typically within a CDN, that serves content to end-users.                                                                                                                                                                                                                 |
| origin bandwidth (origin egress bandwidth)               | The amount of data transferred from the origin server to Cloudflare within a certain period of time. Origin bandwidth is the sum of all EdgeResponseBytes where OriginResponseStatus does not equal 0.                                                                                                               |
| origin server                                            | The original server where the web content is hosted before it is distributed to edge servers in a CDN.                                                                                                                                                                                                               |
| purge                                                    | The process of removing outdated content from the cache to make room for updated content and ensure the delivery of the latest content.                                                                                                                                                                              |
| saved bandwidth (saved egress bandwidth)                 | The percentage of bandwidth saved by caching on the Cloudflare network.                                                                                                                                                                                                                                              |
| static content                                           | Static content, like images, stylesheets, and JavaScript, remains the same for all users. It can be directly served from the cache without fetching from the origin server because it does not change without manual intervention.                                                                                   |
| time-to-live (TTL)                                       | The duration for which a cached copy of a resource is considered valid before it needs to be refreshed or revalidated.                                                                                                                                                                                               |
| total bandwidth (total egress bandwidth, edge bandwidth) | Total bandwidth is the amount of data transferred from Cloudflare to end users within a certain period of time. Total bandwidth equals the sum of all EdgeResponseBytes for a certain period of time.                                                                                                                |
| uncached bandwidth (uncached egress bandwidth)           | Uncached bandwidth is the amount of bandwidth that is not cached and therefore is served from the origin. Uncached bandwidth is the sum of all EdgeResponseBytes where CacheCacheStatus does not equal hit, stale, updating, ignored, or revalidated.                                                                |
| uncached requests                                        | Uncached requests are requests that are not cached and therefore are served from the origin server. Uncached requests are the sum of all requests where CacheCacheStatus does not equal to hit, stale, updating, or ignored.                                                                                         |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/glossary/","name":"Glossary"}}]}
```

---

---
title: Always Online
description: Serve cached pages when your origin server is unavailable.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Always Online

Cloudflare’s Always Online feature is now integrated with the [Internet Archive ↗](https://archive.org/) so that visitors can access a portion of your website even when your origin server is unreachable and a Cloudflare-cached version is unavailable. When your origin is unreachable, Always Online checks Cloudflare’s cache for a stale or expired version of your website. If a version does not exist, Cloudflare goes to the Internet Archive to fetch and serve static portions of your website.

When you enable Always Online with Internet Archive integration, Cloudflare shares your hostname and popular URL paths with the archive so that the Internet Archive’s crawler stores the pages you want archived. When submitting targets to the crawler, Cloudflare identifies the most popular URLs found among GET requests that returned a 200 HTTP status code in the previous five hours.

Note that Cloudflare does not save a copy of every page of your website, and it cannot serve dynamic content while your origin is offline. If the requested page is not in the Internet Archive's Wayback Machine, the visitor sees the actual error page caused by the offline origin web server.

When the Internet Archive integration is enabled, Cloudflare tells the Internet Archive what pages to crawl and how often. The pages to crawl, as previously mentioned, are the most popular URLs that were successfully visited in the last five hours. The crawling intervals, to ensure stability of service, are limited by Cloudflare. Limits vary according to your Cloudflare plan.

## Availability

| Free           | Pro           | Business      | Enterprise   |              |
| -------------- | ------------- | ------------- | ------------ | ------------ |
| Availability   | Yes           | Yes           | Yes          | Yes          |
| Crawl interval | Every 30 days | Every 15 days | Every 5 days | Every 5 days |

## Visitor Experience

When Always Online with Internet Archive integration is enabled, visitors see a banner at the top of the webpage explaining they are visiting an archived version of the website. Visitors can select the Refresh button to check whether the origin has recovered and fresh content is available.

When a visitor requests content and Cloudflare is unable to reach your origin server, Cloudflare returns an HTTP response status code in the range [520–527](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-520/), depending on the issue. These status codes are generated by Cloudflare and indicate that the origin is unreachable. Always Online only activates when Cloudflare cannot connect to your origin — it does not activate when the origin is reachable but returning error responses.

If your origin is reachable and returns a 5xx status code (such as a 520), Always Online will not trigger because the origin is online. Always Online is designed to handle origin unreachability, not origin errors.

When the Internet Archive integration is enabled, Cloudflare checks the archive and serves the most recently archived version of the page.

Visitors who interact with dynamic parts of a website, such as a shopping cart or comment box, will see an error page caused by the offline origin web server.

## Enable Always Online

Here is how to enable Always Online in the dashboard:

1. In the Cloudflare dashboard, go to the **Configuration** page.  
[ Go to **Configuration** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/configuration)
2. Choose the domain that will use Always Online with Internet Archive integration.
3. Under **Always Online**, set the toggle to **On**.

Note

When turning on Always Online, you are also enabling the Internet Archive integration.

Refer to [Always Online](https://developers.cloudflare.com/cache/troubleshooting/always-online/) for best practices, limitations, and FAQs.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/always-online/","name":"Always Online"}}]}
```

---

---
title: Cache keys
description: Customize cache keys to control how Cloudflare stores cached resources.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache keys

A Cache Key is an identifier that Cloudflare uses for a file in our cache, and the Cache Key Template defines the identifier for a given HTTP request.

A default cache key includes:

1. Full URL:  
   * scheme - could be HTTP or HTTPS.  
   * host - for example, `www.cloudflare.com`  
   * URI with query string - for example, `/logo.jpg?utm_source=newsletter`
2. Origin header sent by client (for CORS support).
3. `x-http-method-override`, `x-http-method`, and `x-method-override` headers.
4. `x-forwarded-host`, `x-host`, `x-forwarded-scheme` (unless http or https), `x-original-url`, `x-rewrite-url`, and `forwarded` headers.

## Create custom cache keys

Custom cache keys let you precisely set the cacheability setting for any resource. They provide the benefit of more control, though they may reduce your cache hit rate and result in cache sharding:

1. In the Cloudflare dashboard, go to the **Cache Rules** page.  
[ Go to **Cache Rules** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/cache-rules)
2. Select **Create rule**.
3. Under **When incoming requests match**, define the [rule expression](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/edit-expressions/#expression-builder).
4. Under **Then**, in the **Cache eligibility** section, select **Eligible for cache**.
5. Add the **Cache Key** setting to the rule and select the appropriate **Query String** setting.
6. You can also select settings for **Headers**, **Cookie**, **Host**, and **User**.
7. To save and deploy your rule, select **Deploy**. If you are not ready to deploy your rule, select **Save as Draft**.

Note

When [URL normalization](https://developers.cloudflare.com/rules/normalization/) is enabled, we recommend also enabling [Normalize URLs to origin](https://developers.cloudflare.com/rules/normalization/manage/), especially if you are setting custom cache keys or using cache by device type, which also modifies the cache key. This helps ensure the URL in the cache key matches the URL sent to the origin, preventing cache poisoning and ensuring consistent behavior.

## Cache Key Template

There are a couple of common reasons to change the Cache Key Template. You might change the Cache Key Template to:

* Fragment the cache so one URL is stored in multiple files. For example, to store different files based on a specific query string in the URL.
* Consolidate the cache so different HTTP requests are stored in the same file. For example, to remove the Origin header added to Cloudflare Cache Keys by default.

### Impact of SSL settings on Cache behavior

Cloudflare's `$scheme` variable plays a key role in caching behavior, but its meaning varies depending on the cache key type:

* **Default Cache Key**: `$scheme` refers to the **origin scheme** — the protocol Cloudflare uses to connect to your origin server (HTTP or HTTPS). In this configuration, changes to your SSL settings (for example, switching from Flexible to Full) alter the origin scheme. Because the cache key includes the origin scheme, such changes trigger a cache bust, requiring Cloudflare to fetch content again from the origin.
* **Custom Cache Key**: `$scheme` refers to the **visitor's scheme** — the protocol used by the client making the request to Cloudflare. In this case, SSL setting changes do not impact the cache key unless the origin scheme is explicitly included in your custom configuration.

For example, with Flexible SSL, Cloudflare always connects to the origin over HTTP, regardless of whether the visitor uses HTTP or HTTPS. This results in the same cache key for both protocols under the default configuration.

Be aware that changes in the SSL setting can lead to cache invalidation when using the default cache key:

* Switching from **Off** to **Full**, **Full (strict)**, or **Strict** updates the origin scheme from HTTP to HTTPS, resulting in a cache bust.
* Moving from **Flexible** to **Full**, **Full (strict)**, or **Strict** similarly changes the origin scheme to HTTPS and causes a cache bust.

Understanding how `$scheme` interacts with your caching configuration is essential when modifying SSL modes to avoid unexpected cache behavior.

### Cache Level: Ignore Query String

A [Cache Level](https://developers.cloudflare.com/cache/how-to/set-caching-levels/) of Ignore Query String creates a Cache Key that includes all the elements in the default cache key, except for the query string in the URI that is no longer included. For instance, a request for `http://example.com/file.jpg?something=123` and a request for `http://example.com/file.jpg?something=789` will have the same cache key, in this case.

## Cache Key Settings

The following fields control the Cache Key Template.

### Query String

The query string controls which URL query string parameters go into the Cache Key. You can `include` specific query string parameters or `exclude` them using the respective fields. When you include a query string parameter, the `value` of the query string parameter is used in the Cache Key.

#### Example

If you include the query string foo in a URL like `https://www.example.com/?foo=bar`, then bar appears in the Cache Key. Exactly one of `include` or `exclude` is expected.

#### Usage notes

* To include all query string parameters (the default behavior), use include: `"\*"`
* To ignore query strings, use exclude: `"\*"`
* To include most query string parameters but exclude a few, use the exclude field which assumes the other query string parameters are included.

### Headers

Headers control which headers go into the Cache Key. Similar to Query String, you can include specific headers or exclude default headers.

When you include a header, the header value is included in the Cache Key. For example, if an HTTP request contains an HTTP header like `X-Auth-API-key: 12345`, and you include the `X-Auth-API-Key header` in your Cache Key Template, then `12345` appears in the Cache Key.

In the **Include headers and selected values** section, you can add header names and their values to the cache key. For custom headers, values are optional, but for the following restricted headers, you must include one to 10 specific values:

* `accept`
* `accept-charset`
* `accept-encoding`
* `accept-datetime`
* `accept-language`
* `referer`
* `user-agent`

To check for the presence of a header without including its actual value, use the **Check presence of** option.

Currently, you can only exclude the `Origin` header. The `Origin` header is always included unless explicitly excluded. Including the [Origin header ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Origin) in the Cache Key is important to enforce [CORS ↗](https://developer.mozilla.org/en-US/docs/Glossary/CORS).

Additionally, you cannot include the following headers:

* Headers that re-implement cache or proxy features  
   * `connection`  
   * `content-length`  
   * `cache-control`  
   * `if-match`  
   * `if-modified-since`  
   * `if-none-match`  
   * `if-unmodified-since`  
   * `range`  
   * `upgrade`
* Headers that are covered by other Cache Key features  
   * `cookie`  
   * `host`
* Headers that are specific to Cloudflare and prefixed with `cf-`, for example, `cf-ray`
* Headers that are already included in the custom Cache Key template, for example, `origin`

### Host

Host determines which host header to include in the Cache Key.

* If `Use original host` (`resolved: false` in the API), Cloudflare includes the `Host` header in the HTTP request sent to the origin.
* If `Resolved host` (`resolved: true` in the API), Cloudflare includes the `Host` header that was resolved to get the `origin IP` for the request. The `Host` header may be different from the header actually sent if it has been changed with an [Origin Rule](https://developers.cloudflare.com/rules/origin-rules/features/#dns-record).

### Cookie

Like `query_string` or `header`, `cookie` controls which cookies appear in the Cache Key. You can either include the cookie value or check for the presence of a particular cookie.

#### Usage notes

You cannot include cookies specific to Cloudflare. Cloudflare cookies are prefixed with `__cf`, for example, `__cflb`

### User features

User feature fields add features about the end-user (client) into the Cache Key.

* `device_type` classifies a request as `mobile`, `desktop`, or `tablet` based on the User Agent
* `geo` includes the client’s country, derived from the IP address
* `lang` includes the first language code contained in the `Accept-Language` header sent by the client

## Availability

Cache keys options availability varies according to your plan.

| Free                  | Pro | Business | Enterprise |     |
| --------------------- | --- | -------- | ---------- | --- |
| Cache deception armor | Yes | Yes      | Yes        | Yes |
| Cache by device type  | Yes | Yes      | Yes        | Yes |
| Ignore query string   | Yes | Yes      | Yes        | Yes |
| Sort query string     | Yes | Yes      | Yes        | Yes |
| Query string          | No  | No       | No         | Yes |
| Headers               | No  | No       | No         | Yes |
| Cookie                | No  | No       | No         | Yes |
| Host                  | No  | No       | No         | Yes |
| User features         | No  | No       | No         | Yes |

## Troubleshooting

You can use [Cloudflare Trace](https://developers.cloudflare.com/rules/trace-request/) to find which Cache Key settings were applied to your request. When you send a request through the Trace tool, if the request was served from cache, it will show a cache hit in the **Cache Parameters** section. Then select **View parameter detail** to see exactly which Cache Key properties were used.

## Limitations

The [Prefetch](https://developers.cloudflare.com/speed/optimization/content/prefetch-urls/) feature is not compatible with the [Custom Cache Keys](https://developers.cloudflare.com/cache/how-to/cache-rules/examples/custom-cache-key/). With [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/), the custom cache key is used to cache all assets. However, Prefetch always uses the default cache key. This results in a key mismatch.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-keys/","name":"Cache keys"}}]}
```

---

---
title: Cache Response Rules
description: Control response headers and settings for cached content.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache Response Rules

Cache Response Rules allow you to configure cache settings based on request and response attributes. These rules execute prior to caching in the `http_response_cache_settings` phase, which runs after Cloudflare receives the origin response.

With Cache Response Rules you can:

* Modify `Cache-Control` directives sent by your origin.
* Modify cache tags on responses for targeted [cache purging](https://developers.cloudflare.com/cache/how-to/purge-cache/).
* Strip headers (`ETag`, `Set-Cookie`, `Last-Modified`) from origin responses before caching.

Cache Response Rules apply to both cached and non-cached (dynamic) responses from the origin. For example, you can strip Set-Cookie headers from responses that are not eligible for caching.

Cache Response Rules can be created in the [dashboard](https://developers.cloudflare.com/cache/how-to/cache-response-rules/create-dashboard/), via [API](https://developers.cloudflare.com/cache/how-to/cache-response-rules/create-api/), or [Terraform](https://developers.cloudflare.com/cache/how-to/cache-response-rules/terraform-example/).

Note

Cache Response Rules require that you [proxy the DNS records](https://developers.cloudflare.com/dns/proxy-status/) of your domain (or subdomain) through Cloudflare.

## Availability

The following table describes Cache Response Rules availability per plan.

| Free            | Pro | Business | Enterprise |     |
| --------------- | --- | -------- | ---------- | --- |
| Availability    | Yes | Yes      | Yes        | Yes |
| Number of rules | 10  | 25       | 50         | 300 |

## Troubleshooting

When troubleshooting Cache Response Rules, use [Cloudflare Trace](https://developers.cloudflare.com/rules/trace-request/) to determine if a rule is triggering for a specific URL.

## Relationship with Cache Rules

Cache Response Rules operate on the origin response, while [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/) operate on the incoming request. When settings from both rule types conflict, Cache Response Rules take precedence.

Key differences:

* **Cache eligibility**: Cache Rules remain the only mechanism to decide whether content is eligible for caching. However, Cache Response Rules can make a cacheable asset non-cacheable by setting the `no-store` directive using the `set_cache_control` action.
* **Origin Cache Control (OCC)**: If any rule in the `http_response_cache_settings` phase matches, Cloudflare defaults to Origin Cache Control behavior (`origin_cache_control = true`).
* **CDN-Cache-Control precedence**: `Cache-Control` directives set by Cache Response Rules take precedence over origin-set `Cloudflare-CDN-Cache-Control` and `CDN-Cache-Control` headers. For more information, refer to [CDN-Cache-Control header precedence](https://developers.cloudflare.com/cache/concepts/cdn-cache-control/#header-precedence).
* **Stacking**: Cache Response Rules stack the same way as Cache Rules. When multiple rules specify the same setting, the last matching rule wins.

### Example: OCC precedence over Edge TTL

Consider the following scenario:

1. A Cache Rule sets **Edge TTL** to `override_origin` with a value of `7200` seconds (2 hours).
2. A Cache Response Rule uses `set_cache_control` to set `s-maxage` to `3600` seconds (1 hour) with `cloudflare_only` enabled.
3. The origin responds with `Cache-Control: s-maxage=600`.

In this case, the Cache Response Rule takes precedence. Cloudflare caches the asset for `3600` seconds (1 hour) based on the `s-maxage` directive set by the Cache Response Rule, while visitors still receive the original `s-maxage=600` from the origin because `cloudflare_only` is enabled.

## Notes

* If you strip last modified then Smart Edge Revalidation will be turned off.
* Cache Response Rules ignore [1xx HTTP response status codes](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/1xx-informational/) as they are treated as informational responses.
* Cache Response Rules can be versioned. Refer to the [Version Management](https://developers.cloudflare.com/version-management/) documentation for more information.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-response-rules/","name":"Cache Response Rules"}}]}
```

---

---
title: Create a rule via API
description: Create cache response rules using the Rulesets API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Create a rule via API

Use the [Rulesets API](https://developers.cloudflare.com/ruleset-engine/rulesets-api/) to create a Cache Response Rule via API. To configure the Cloudflare API, refer to the [API documentation](https://developers.cloudflare.com/fundamentals/api/get-started/).

## Basic rule settings

When creating a Cache Response Rule via API, make sure you:

* Set the rule action to one of the [available actions](https://developers.cloudflare.com/cache/how-to/cache-response-rules/settings/#available-actions).
* Define the parameters in the `action_parameters` field according to the [settings](https://developers.cloudflare.com/cache/how-to/cache-response-rules/settings/) you wish to configure for matching responses.
* Deploy the rule to the `http_response_cache_settings` phase entry point ruleset.

## Procedure

1. Use the [List zone rulesets](https://developers.cloudflare.com/api/resources/rulesets/methods/list/) method to check if a ruleset already exists for the `http_response_cache_settings` phase.
2. If the phase ruleset does not exist, create it using the [Create a zone ruleset](https://developers.cloudflare.com/api/resources/rulesets/methods/create/) operation. In the new ruleset properties, set the following values:  
   * kind: `zone`  
   * phase: `http_response_cache_settings`
3. Use the [Update a zone ruleset](https://developers.cloudflare.com/api/resources/rulesets/methods/update/) operation to add rules to the ruleset. Alternatively, include the rules in the [Create a zone ruleset](https://developers.cloudflare.com/api/resources/rulesets/methods/create/) request mentioned in the previous step.

## Example requests

These examples demonstrate all the available actions in Cache Response Rules using request and response matching criteria. Using these examples directly will cause any existing rules in the phase to be replaced.

Example: Strip response headers from JS files before caching

Update a zone entry point ruleset

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/phases/http_response_cache_settings/entrypoint" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "rules": [

        {

            "expression": "http.request.uri.path.extension eq \"js\"",

            "description": "Strip caching headers from JS files",

            "action": "set_cache_settings",

            "action_parameters": {

                "strip_etags": true,

                "strip_set_cookie": true,

                "strip_last_modified": true

            }

        }

    ]

  }'


```

Example: Set static cache tags on API responses

Update a zone entry point ruleset

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/phases/http_response_cache_settings/entrypoint" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "rules": [

        {

            "expression": "http.request.uri.path starts_with \"/api/\"",

            "description": "Tag API responses for targeted purging",

            "action": "set_cache_tags",

            "action_parameters": {

                "operation": "set",

                "values": [

                    "api-response",

                    "dynamic-content"

                ]

            }

        }

    ]

  }'


```

Example: Add cache tags from a response header using an expression

Update a zone entry point ruleset

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/phases/http_response_cache_settings/entrypoint" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "rules": [

        {

            "expression": "any(http.response.headers.names[*] == \"Surrogate-Keys\")",

            "description": "Extract cache tags from alternative CDN response header",

            "action": "set_cache_tags",

            "action_parameters": {

                "operation": "add",

                "expression": "split(http.response.headers[\"Surrogate-Keys\"][0], \",\", 1)"

            }

        }

    ]

  }'


```

Example: Override cache-control with max-age 

Update a zone entry point ruleset

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/phases/http_response_cache_settings/entrypoint" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "rules": [

        {

            "expression": "http.response.code eq 200",

            "description": "Override cache-control for successful responses",

            "action": "set_cache_control",

            "action_parameters": {

                "max-age": {

                    "operation": "set",

                    "value": 3600,

                    "cloudflare_only": true

                }

            }

        }

    ]

  }'


```

Example: Set private directive with qualifiers

Update a zone entry point ruleset

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/phases/http_response_cache_settings/entrypoint" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "rules": [

        {

            "expression": "http.request.uri.path starts_with \"/user/\"",

            "description": "Mark user content as private",

            "action": "set_cache_control",

            "action_parameters": {

                "private": {

                    "operation": "set",

                    "qualifiers": [

                        "X-User-Id",

                        "X-Session-Token"

                    ]

                },

                "no-cache": {

                    "operation": "set"

                }

            }

        }

    ]

  }'


```

Example: Set immutable for static font assets

Update a zone entry point ruleset

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/phases/http_response_cache_settings/entrypoint" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "rules": [

        {

            "expression": "http.request.uri.path.extension in {\"woff2\" \"woff\" \"ttf\"}",

            "description": "Mark fonts as immutable",

            "action": "set_cache_control",

            "action_parameters": {

                "immutable": {

                    "operation": "set"

                },

                "max-age": {

                    "operation": "set",

                    "value": 31536000

                }

            }

        }

    ]

  }'


```

Example: Multiple rules with strip headers, tag responses, and set cache control

Update a zone entry point ruleset

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/phases/http_response_cache_settings/entrypoint" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "rules": [

        {

            "expression": "http.response.code eq 200 and http.request.uri.path.extension eq \"html\"",

            "description": "Strip tracking headers from HTML responses",

            "action": "set_cache_settings",

            "action_parameters": {

                "strip_etags": true,

                "strip_set_cookie": true

            }

        },

        {

            "expression": "http.request.uri.path starts_with \"/products/\"",

            "description": "Tag product pages for purging",

            "action": "set_cache_tags",

            "action_parameters": {

                "operation": "add",

                "values": [

                    "product-catalog",

                    "storefront"

                ]

            }

        },

        {

            "expression": "http.response.code eq 200",

            "description": "Set cache control for all 200 responses",

            "action": "set_cache_control",

            "action_parameters": {

                "s-maxage": {

                    "operation": "set",

                    "value": 86400,

                    "cloudflare_only": true

                },

                "must-revalidate": {

                    "operation": "set"

                }

            }

        }

    ]

  }'


```

## Required API token permissions

The API token used in API requests to manage Cache Response Rules must have the following permissions:

* _Zone_ \> _Cache Rules_ \> _Edit_
* _Account Rulesets_ \> _Edit_
* _Account Filter Lists_ \> _Edit_

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-response-rules/","name":"Cache Response Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-response-rules/create-api/","name":"Create a rule via API"}}]}
```

---

---
title: Create a rule in the dashboard
description: Create cache response rules in the Cloudflare dashboard.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Create a rule in the dashboard

1. In the Cloudflare dashboard, go to **Cache** \> **Cache Rules**.  
[ Go to **Cache Rules** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/cache-rules)
2. Select the **Cache Response Rules** tab.
3. Select **Create rule**.
4. Enter a descriptive name for the rule in **Rule name**.
5. Under **When incoming requests match**, select **All incoming requests** if you want the rule to apply to all traffic or **Custom filter expression** if you want the rule to only apply to traffic matching the custom expression.
6. If you selected **Custom filter expression**, define the [rule expression](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/edit-expressions/#expression-builder). Use the **Field** drop-down list to choose an HTTP property and select an **Operator**. Both request fields (such as URI path or hostname) and response fields (such as response status code or response headers) are available for matching. Refer to [Available settings](https://developers.cloudflare.com/cache/how-to/cache-response-rules/settings/) for the full list of available fields and operators.  
Note  
Rules can be further customized by using the **Edit expression** option. You can find more information in [Edit expressions in the dashboard](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/edit-expressions/).
7. Following the selection of the field and operator, enter the corresponding value that will trigger the Cache Response Rule. For example, if the selected field is `Hostname` and the operator is `equals`, a value of `example.com` would mean the rule matches any request to that hostname.
8. Under **Then**, select one of the following actions:  
   * **Modify cache-control directives**: Set or remove `Cache-Control` directives sent by your origin. For each directive, choose **Set directive** or **Remove directive**. For duration-based directives like `max-age` or `s-maxage`, enter a value in seconds. Turn on **Cloudflare only** to apply the directive only within Cloudflare's cache without changing what visitors receive. Refer to [Supported directives](https://developers.cloudflare.com/cache/how-to/cache-response-rules/settings/#supported-directives) for the full list.  
   * **Modify cache tags**: Add, override, or remove cache tags on the response for targeted [purging](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-tags/). Select one of the following operations:  
         * **Add to existing tags**: Append new tags to the current set.  
         * **Override existing tags**: Replace all current tags with the specified tags.  
         * **Remove from existing tags**: Remove specific tags from the current set.  
   For the tag source, you can either specify tags manually or select **Parse from response header** to extract tags from a response header value. When parsing from a header, you can split the header value using a custom separator (for example, commas instead of spaces).  
   * **Strip headers**: Remove `Set-Cookie`, `ETag`, or `Last-Modified` headers from the origin response before Cloudflare evaluates the response for caching. Select which headers to strip.  
For more details on each action, refer to [Available settings](https://developers.cloudflare.com/cache/how-to/cache-response-rules/settings/#available-actions).
9. Under **Place at**, from the dropdown, you can select the order of your rule. From the main page, you can also change the order of the rules you have created.
10. To save and deploy your rule, select **Deploy**. If you are not ready to deploy your rule, select **Save as Draft**.

If you are matching a hostname in your rule expression, you may be prompted to create a proxied DNS record for that hostname. Refer to [Troubleshooting](https://developers.cloudflare.com/rules/reference/troubleshooting/#this-rule-may-not-apply-to-your-traffic) for more information.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-response-rules/","name":"Cache Response Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-response-rules/create-dashboard/","name":"Create a rule in the dashboard"}}]}
```

---

---
title: Available settings
description: Available settings for cache response rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Available settings

These are the settings that you can configure when creating a Cache Response Rule. Because Cache Response Rules execute after Cloudflare receives the origin response, both request and response fields are available for rule matching.

## Expression fields

### Request fields

| Field                            | Type   | Description                                    |
| -------------------------------- | ------ | ---------------------------------------------- |
| http.cookie                      | String | Full cookie header value                       |
| http.host                        | String | The HTTP Host header                           |
| http.referer                     | String | The HTTP Referer header                        |
| http.user\_agent                 | String | The HTTP User-Agent header                     |
| http.request.method              | String | The HTTP request method                        |
| http.request.uri                 | String | The request URI                                |
| http.request.uri.path            | String | The URI path                                   |
| http.request.uri.path.basename   | String | The basename of the URI path                   |
| http.request.uri.path.extension  | String | The file extension from the URI path           |
| http.request.uri.query           | String | The query string                               |
| http.request.uri.args            | Map    | Query string arguments as key-value pairs      |
| http.request.uri.args.names      | Array  | Query string argument names                    |
| http.request.uri.args.values     | Array  | Query string argument values                   |
| http.request.full\_uri           | String | The full request URI including scheme and host |
| http.request.headers             | Map    | Request headers as key-value pairs             |
| http.request.headers.names       | Array  | Request header names                           |
| http.request.headers.values      | Array  | Request header values                          |
| http.request.cookies             | Map    | Parsed cookies as key-value pairs              |
| http.request.accepted\_languages | Array  | Parsed Accept-Language header values           |

### Response fields

| Field                        | Type    | Description                                   |
| ---------------------------- | ------- | --------------------------------------------- |
| http.response.code           | Integer | The HTTP response status code from the origin |
| http.response.headers        | Map     | Response headers as key-value pairs           |
| http.response.headers.names  | Array   | Response header names                         |
| http.response.headers.values | Array   | Response header values                        |

If you select the [Edit expression](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/edit-expressions/#expression-editor) option, you can enter any of the above response fields.

## Functions

The following functions are available in this phase:

* all
* any
* concat
* decode\_base64
* ends\_with
* len
* lookup\_json\_integer
* lookup\_json\_string
* lower
* regex\_replace
* remove\_bytes
* remove\_query\_args
* split
* starts\_with
* substring
* to\_string
* upper
* url\_decode
* wildcard\_replace

For descriptions of each function, refer to [Functions](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/).

## Operators

For the full list of operators, refer to [Operators](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/).

## Available actions

Cache Response Rules support three actions:

| Action               | Description                                                                               |
| -------------------- | ----------------------------------------------------------------------------------------- |
| set\_cache\_settings | Strip headers (ETags, Set-Cookie, Last-Modified) from the origin response before caching. |
| set\_cache\_tags     | Add, remove, or set cache tags on the response for targeted purging.                      |
| set\_cache\_control  | Modify Cache-Control header directives in the origin response.                            |

---

### Action: set\_cache\_settings

Configures settings related to caching on the origin response. The following parameters are available:

| Parameter             | Type    | Description                                                          |
| --------------------- | ------- | -------------------------------------------------------------------- |
| strip\_etags          | Boolean | Strip ETag headers from the origin response before caching.          |
| strip\_set\_cookie    | Boolean | Strip Set-Cookie headers from the origin response before caching.    |
| strip\_last\_modified | Boolean | Strip Last-Modified headers from the origin response before caching. |

Note

If `strip_etags` or `strip_last_modified` is `true` after all matching rules are applied, [Smart Edge Revalidation ↗](https://blog.cloudflare.com/introducing-smart-edge-revalidation/) is disabled for the origin response.

API information

API action: `set_cache_settings`.

API configuration example

```

"action_parameters": {

  "strip_etags": true,

  "strip_set_cookie": true,

  "strip_last_modified": true

}


```

Refer to [Create a rule via API](https://developers.cloudflare.com/cache/how-to/cache-response-rules/create-api/) for complete API examples.

---

### Action: set\_cache\_tags

Modifies the cache tags associated with the response. Cache tags can be used for targeted [cache purging](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-tags/).

| Parameter  | Type   | Description                                                                             |
| ---------- | ------ | --------------------------------------------------------------------------------------- |
| operation  | String | **Required.** One of: add, remove, set.                                                 |
| values     | Array  | A list of cache tag strings. Mutually exclusive with expression.                        |
| expression | String | An expression that evaluates to an array of cache tags. Mutually exclusive with values. |

API information

API action: `set_cache_tags`.

API configuration example (static values)

```

"action_parameters": {

  "operation": "set",

  "values": ["api-response", "dynamic-content"]

}


```

API configuration example (expression)

```

"action_parameters": {

  "operation": "add",

  "expression": "split(http.response.headers[\"Surrogate-Keys\"][0], \",\", 1)"

}


```

Refer to [Create a rule via API](https://developers.cloudflare.com/cache/how-to/cache-response-rules/create-api/) for complete API examples.

---

### Action: set\_cache\_control

Modifies Cache-Control header directives in the origin response.

#### Supported directives

**Directives with duration value (seconds):**

* `max-age`
* `s-maxage`
* `stale-if-error`
* `stale-while-revalidate`

**Directives with optional qualifiers (header names):**

* `private`
* `no-cache`

**Boolean directives:**

* `no-store`
* `no-transform`
* `must-revalidate`
* `proxy-revalidate`
* `must-understand`
* `public`
* `immutable`

#### Directive configuration

The available parameters depend on the directive type.

##### Directives with duration value

Applies to `max-age`, `s-maxage`, `stale-if-error`, and `stale-while-revalidate`.

| Parameter        | Type    | Description                                                                                                                     |
| ---------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------- |
| operation        | String  | **Required.** set or remove.                                                                                                    |
| cloudflare\_only | Boolean | When enabled, this setting only affects how Cloudflare caches your content. Your visitors still receive the original directive. |
| value            | Integer | Duration in seconds. **Required when operation is set.**                                                                        |

##### Directives with optional qualifiers

Applies to `private` and `no-cache`.

| Parameter        | Type    | Description                                                                                                                     |
| ---------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------- |
| operation        | String  | **Required.** set or remove.                                                                                                    |
| cloudflare\_only | Boolean | When enabled, this setting only affects how Cloudflare caches your content. Your visitors still receive the original directive. |
| qualifiers       | Array   | Optional list of header names to qualify the directive.                                                                         |

##### Boolean directives

Applies to `no-store`, `no-transform`, `must-revalidate`, `proxy-revalidate`, `must-understand`, `public`, and `immutable`.

| Parameter        | Type    | Description                                                                                                                     |
| ---------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------- |
| operation        | String  | **Required.** set or remove.                                                                                                    |
| cloudflare\_only | Boolean | When enabled, this setting only affects how Cloudflare caches your content. Your visitors still receive the original directive. |

API information

API action: `set_cache_control`.

API configuration example

```

"action_parameters": {

  "max-age": {

    "operation": "set",

    "value": 3600,

    "cloudflare_only": true

  },

  "stale-if-error": {

    "operation": "remove"

  }

}


```

Refer to [Create a rule via API](https://developers.cloudflare.com/cache/how-to/cache-response-rules/create-api/) for complete API examples.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-response-rules/","name":"Cache Response Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-response-rules/settings/","name":"Available settings"}}]}
```

---

---
title: Terraform example
description: Create cache response rules using Terraform.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Terraform example

The following example defines a single Cache Response Rule for a zone using Terraform. The rule strips Set-Cookie and ETag headers from JavaScript file responses before caching.

Terraform `cloudflare_ruleset` resource

```

# Cache Response Rule to strip headers from JS responses

resource "cloudflare_ruleset" "cache_response_rules_example" {

  zone_id     = "<ZONE_ID>"

  name        = "Cache Response Rules"

  description = "Configure cache settings for origin responses"

  kind        = "zone"

  phase       = "http_response_cache_settings"


  rules {

    ref         = "strip_js_headers"

    description = "Strip caching headers from JS file responses"

    expression  = "http.request.uri.path.extension eq \"js\""

    action      = "set_cache_settings"

    action_parameters {

      strip_etags      = true

      strip_set_cookie = true

    }

  }


  rules {

    ref         = "tag_api_responses"

    description = "Tag API responses for targeted purging"

    expression  = "starts_with(http.request.uri.path, \"/api/\")"

    action      = "set_cache_tags"

    action_parameters {

      operation = "set"

      values    = ["api-response", "dynamic-content"]

    }

  }


  rules {

    ref         = "cache_control_200"

    description = "Set cache-control for successful responses"

    expression  = "http.response.code eq 200"

    action      = "set_cache_control"

    action_parameters {

      s_maxage {

        operation      = "set"

        value          = 86400

        cloudflare_only = true

      }

      must_revalidate {

        operation = "set"

      }

    }

  }

}


```

Use the `ref` field to get stable rule IDs across updates when using Terraform. Adding this field prevents Terraform from recreating the rule on changes. For more information, refer to [Troubleshooting](https://developers.cloudflare.com/terraform/troubleshooting/rule-id-changes/#how-to-keep-the-same-rule-id-between-modifications) in the Terraform documentation.

For additional guidance on using Terraform with Cloudflare, refer to [Terraform](https://developers.cloudflare.com/terraform/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-response-rules/","name":"Cache Response Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-response-rules/terraform-example/","name":"Terraform example"}}]}
```

---

---
title: Cache Rules
description: Control what and how Cloudflare caches with Cache Rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache Rules

Use Cache Rules to customize cache settings on Cloudflare. Cache Rules allows you to make adjustments to what is eligible to cache, how long it should be cached and where, as well as trigger specific interactions with Cloudflare's cache and other Rules products for matching requests.

Cache Rules can be created in the [dashboard](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/), via [API](https://developers.cloudflare.com/cache/how-to/cache-rules/create-api/) or [Terraform](https://developers.cloudflare.com/cache/how-to/cache-rules/terraform-example/).

Notes

Cache Rules require that you [proxy the DNS records](https://developers.cloudflare.com/dns/proxy-status/) of your domain (or subdomain) through Cloudflare.

Rules can be versioned. Refer to the [Version Management](https://developers.cloudflare.com/version-management/) documentation for more information.

## Rules templates

Cloudflare provides you with rules templates for common use cases.

1. In the Cloudflare dashboard, go to the Rules **Overview** page.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/rules/overview)
2. Select **Templates**, and then select one of the available templates.

You can also refer to the [Examples gallery](https://developers.cloudflare.com/rules/examples/) in the developer docs.

## Availability

The following table describes Cache Rules availability per plan.

| Free            | Pro | Business | Enterprise |     |
| --------------- | --- | -------- | ---------- | --- |
| Availability    | Yes | Yes      | Yes        | Yes |
| Number of rules | 10  | 25       | 50         | 300 |

## Troubleshooting

When troubleshooting Cache Rules, use [Cloudflare Trace](https://developers.cloudflare.com/rules/trace-request/) to determine if a rule is triggering for a specific URL.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}}]}
```

---

---
title: Create a rule via API
description: Create cache rules using the Rulesets API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Create a rule via API

Use the [Rulesets API](https://developers.cloudflare.com/ruleset-engine/rulesets-api/) to create a cache rule via API. To configure Cloudflare’s API refer to the [API documentation](https://developers.cloudflare.com/fundamentals/api/get-started/).

## Basic rule settings

When creating a cache rule via API, make sure you:

* Set the rule action to `set_cache_settings`.
* Define the parameters in the `action_parameters` field according to the [settings](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/) you wish to override for matching requests.
* Deploy the rule to the `http_request_cache_settings` phase entry point ruleset.

## Procedure

1. Use the [List zone rulesets](https://developers.cloudflare.com/api/resources/rulesets/methods/list/) method to obtain the list of rules already present in the `http_request_cache_settings` phase entry point ruleset.
2. If the phase ruleset does not exist, create it using the [Create a zone ruleset](https://developers.cloudflare.com/api/resources/rulesets/methods/create/) operation. In the new ruleset properties, set the following values:  
   * kind: `zone`  
   * phase: `http_request_cache_settings`
3. Use the [Update a zone ruleset](https://developers.cloudflare.com/api/resources/rulesets/methods/update/) operation to add a cache rule to the list of ruleset rules. Alternatively, include the rule in the [Create a zone ruleset](https://developers.cloudflare.com/api/resources/rulesets/methods/create/) request mentioned in the previous step.
4. (Optional) To update an existing cache rule, use the [Update a zone ruleset rule](https://developers.cloudflare.com/api/resources/rulesets/methods/update/) operation. For an example, refer to the section below.

## Example requests

These examples are setting all the Cache Rules of a zone to a single rule, since using these examples directly will cause any existing rules to be deleted.

Example: Cache everything for example.com

Update a zone ruleset

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/$RULESET_ID" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "rules": [

        {

            "expression": "(http.host eq \"example.com\")",

            "description": "cache everything for example.com",

            "action": "set_cache_settings",

            "action_parameters": {

                "cache": true

            }

        }

    ]

  }'


```

Example: Extend read timeout for Android clients

Update a zone ruleset

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/$RULESET_ID" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "rules": [

        {

            "expression": "(http.user_agent contains \"Android\")",

            "description": "extend read timeout for android clients",

            "action": "set_cache_settings",

            "action_parameters": {

                "cache": true,

                "read_timeout": 300

            }

        }

    ]

  }'


```

Example: Disable Cache Reserve for frequently updated assets

Update a zone ruleset

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/$RULESET_ID" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "rules": [

        {

            "expression": "(starts_with(http.request.uri, \"/feed/\"))",

            "description": "disable cache reserve for frequently updated assets",

            "action": "set_cache_settings",

            "action_parameters": {

                "cache": true,

                "cache_reserve": {

                    "enabled": false

                }

            }

        }

    ]

  }'


```

Example: Turn off default cache TTLs

Update a zone ruleset

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/$RULESET_ID" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "rules": [

        {

            "expression": "(http.host eq \"example.com\")",

            "description": "turn off default cache ttls",

            "action": "set_cache_settings",

            "action_parameters": {

                "cache": true,

                "edge_ttl": {

                    "mode": "bypass_by_default"

                }

            }

        }

    ]

  }'


```

Example: Update the position of an existing rule

Update a zone ruleset rule

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/$RULESET_ID/rules/$RULE_ID" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "expression": "(http.host eq \"example.com\")",

    "description": "cache everything for example.com",

    "action": "set_cache_settings",

    "action_parameters": {

        "cache": true

    },

    "enabled": true,

    "position": {

        "before": "da5e8e506c8e7877fe06cdf4c41add54"

    }

  }'


```

## Required API token permissions

The API token used in API requests to manage Cache Rules must have the following permissions:

* _Zone_ \> _Cache Rules_ \> _Edit_
* _Account Rulesets_ \> _Edit_
* _Account Filter Lists_ \> _Edit_

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/create-api/","name":"Create a rule via API"}}]}
```

---

---
title: Create a rule in the dashboard
description: Create cache rules in the Cloudflare dashboard.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Create a rule in the dashboard

1. In the Cloudflare dashboard, go to the **Cache Rules** page.  
[ Go to **Cache Rules** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/cache-rules)
2. Select **Create rule**.
3. (Optional) Select one of the rule templates that address common use cases. Then, review and adjust the proposed rule configuration.
4. Enter a descriptive name for the rule in **Rule name**.
5. Under **When incoming requests match**, select **All incoming requests** if you want the rule to apply to all traffic or **Custom filter expression** if you want the rule to only apply to traffic matching the custom expression.
6. If you selected **Custom filter expression**, under **When incoming requests match**, define the [rule expression](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/edit-expressions/#expression-builder). Use the **Field** drop-down list to choose an HTTP property and select an **Operator**. Refer to [Available settings](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/) for the list of available fields and operators.  
![Select fields in the Expression Builder.](https://developers.cloudflare.com/_astro/select-fields.euDkKViI_ZPmSQ0.webp)
7. Following the selection of the field and operator, enter the corresponding value that will trigger the Cache Rule. For example, if the selected field is `Hostname` and the operator is `equals`, a value of `cloudflare.com` would mean the rule matches any request to that hostname.  
![Example rule](https://developers.cloudflare.com/_astro/example-rule.fBosjk1F_ZeT0Gp.webp)  
Note  
Rules can be further customized by using the **Edit expression** option. You can find more information in [Edit expressions in the dashboard](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/edit-expressions/).
8. Under **Then**, in the **Cache eligibility** section, select [**Bypass cache**](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#bypass-cache) if you want matching requests to not be cacheable, or **Eligible for cache** if you want Cloudflare to attempt to cache them. Note that [cache-control headers](https://developers.cloudflare.com/cache/concepts/cache-control/) can also impact cache eligibility.
9. If you selected **Eligible for cache** in the previous step, you can customize the options described in the [Available settings](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/) section.
10. Under **Place at**, from the dropdown, you can select the order of your rule. From the main page, you can also change the order of the rules you have created.
11. To save and deploy your rule, select **Deploy**. If you are not ready to deploy your rule, select **Save as Draft**.  
If you are matching a hostname in your rule expression, you may be prompted to create a proxied DNS record for that hostname. Refer to [Troubleshooting](https://developers.cloudflare.com/rules/reference/troubleshooting/#this-rule-may-not-apply-to-your-traffic) for more information.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/create-dashboard/","name":"Create a rule in the dashboard"}}]}
```

---

---
title: Browser Cache TTL
description: Browser Cache TTL
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Browser Cache TTL

Browser Cache TTL

Note

If you are migrating from Page Rules and you want to keep Page Rules behavior, you need to create two specific rules before creating this rule. For more details refer to [Migration from Page Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/page-rules-migration/).

[Create a cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/) to adjust browser cache TTL for caching resources in the browser to one day for any hostname containing `example.com`:

* **When incoming requests match**: Custom filter expression  
   * Using the Expression Builder:  
   `Hostname contains "example.com"`  
   * Using the Expression Editor:  
   `(http.host contains "example.com")`
* **Then**:  
   * **Cache eligibility**: Eligible for cache  
   * **Browser TTL**: Override origin and use this TTL  
   * **Input time-to-live (TTL)**: _1 day_

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/examples/","name":"Examples"}},{"@type":"ListItem","position":6,"item":{"@id":"/cache/how-to/cache-rules/examples/browser-cache-ttl/","name":"Browser Cache TTL"}}]}
```

---

---
title: Bypass Cache on Cookie
description: Bypass Cache on Cookie
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Bypass Cache on Cookie

Bypass Cache on Cookie

Note

If you are migrating from Page Rules and you want to keep Page Rules behavior, you need to create two specific rules before creating this rule. For more details refer to [Migration from Page Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/page-rules-migration/).

[Create a cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/) to bypass cache for requests containing cookie `test_cookie` for any hostname containing `example.com`:

* **When incoming requests match**: Custom filter expression  
   * Using the Expression Builder:  
   `Hostname contains "example.com" AND Cookie contains "test-cookie"`  
   * Using the Expression Editor:  
   `(http.host contains "example.com" and http.cookie contains "test-cookie")`
* **Then**:  
   * **Cache eligibility**: Bypass cache

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/examples/","name":"Examples"}},{"@type":"ListItem","position":6,"item":{"@id":"/cache/how-to/cache-rules/examples/bypass-cache-on-cookie/","name":"Bypass Cache on Cookie"}}]}
```

---

---
title: Cache everything for hostnames in a list
description: Cache everything for hostnames in a list
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache everything for hostnames in a list

Cache everything for hostnames in a list

[Create a cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/) to cache everything for hostnames that match a [custom hostname list](https://developers.cloudflare.com/waf/tools/lists/custom-lists/#lists-with-hostnames):

* **When incoming requests match**: Custom filter expression  
   * Using the Expression Builder:  
   `Hostname is in list "my_hostnames"`  
   * Using the Expression Editor:  
   `(http.host in $my_hostnames)`
* **Then**:  
   * **Cache eligibility**: Eligible for cache

Note

The **is in list** operator requires an Enterprise plan. You must first [create a hostname list](https://developers.cloudflare.com/waf/tools/lists/create-dashboard/) in your account before you can reference it in a cache rule expression.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/examples/","name":"Examples"}},{"@type":"ListItem","position":6,"item":{"@id":"/cache/how-to/cache-rules/examples/cache-by-hostname-list/","name":"Cache everything for hostnames in a list"}}]}
```

---

---
title: Cache Deception Armor
description: Cache Deception Armor
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache Deception Armor

Cache Deception Armor

Note

If you are migrating from Page Rules and you want to keep Page Rules behavior, you need to create two specific rules before creating this rule. For more details refer to [Migration from Page Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/page-rules-migration/).

[Create a cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/) to protect against cache deception attacks for any hostname containing `example.com`:

* **When incoming requests match**: Custom filter expression  
   * Using the Expression Builder:  
   `Hostname contains "example.com"`  
   * Using the Expression Editor:  
   `(http.host contains "example.com")`
* **Then**:  
   * **Cache eligibility**: Eligible for cache  
   * **Setting**: Cache key  
         * **Cache deception armor**: On

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/examples/","name":"Examples"}},{"@type":"ListItem","position":6,"item":{"@id":"/cache/how-to/cache-rules/examples/cache-deception-armor/","name":"Cache Deception Armor"}}]}
```

---

---
title: Cache by Device Type
description: Cache by Device Type
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache by Device Type

Cache by Device Type

Note

If you are migrating from Page Rules and you want to keep Page Rules behavior, you need to create two specific rules before creating this rule. For more details refer to [Migration from Page Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/page-rules-migration/).

[Create a cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/) to cache content based on user agent or device type for any hostname containing `example.com`:

* **When incoming requests match**: Custom filter expression  
   * Using the Expression Builder:  
   `Hostname contains "example.com"`  
   * Using the Expression Editor:  
   `(http.host contains "example.com")`
* **Then**:  
   * **Cache eligibility**: Eligible for cache  
   * **Setting**: Cache key  
         * **Cache by device type**: On

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/examples/","name":"Examples"}},{"@type":"ListItem","position":6,"item":{"@id":"/cache/how-to/cache-rules/examples/cache-device-type/","name":"Cache by Device Type"}}]}
```

---

---
title: Cache Level (Cache Everything)
description: Cache Level (Cache Everything)
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache Level (Cache Everything)

Cache Level (Cache Everything)

Note

If you are migrating from Page Rules and you want to keep Page Rules behavior, you need to create two specific rules before creating this rule. For more details refer to [Migration from Page Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/page-rules-migration/).

[Create a cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/) to adjust cache level for any hostname containing `example.com`:

* **When incoming requests match**: Custom filter expression  
   * Using the Expression Builder:  
   `Hostname contains "example.com"`  
   * Using the Expression Editor:  
   `(http.host contains "example.com")`
* **Then**:  
   * **Cache eligibility**: Eligible for cache

Warning

This option caches all HTML regardless of the presence of dynamic content. If you use this approach to cache pages containing dynamic content, visitors may receive information not intended for them. To avoid caching dynamic content, you can add a condition to the rule's matching criteria to prevent it from matching that content. Some examples include:

* Checking for the presence of a cookie.
* Negative matching against known dynamic content file paths.
* Negative matching against dynamic content extensions (or lack of an extension).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/examples/","name":"Examples"}},{"@type":"ListItem","position":6,"item":{"@id":"/cache/how-to/cache-rules/examples/cache-everything/","name":"Cache Level (Cache Everything)"}}]}
```

---

---
title: Cache Everything while ignoring query strings
description: Cache Everything while ignoring query strings
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache Everything while ignoring query strings

Cache Everything while ignoring query strings

Note

If you are migrating from Page Rules and you want to keep Page Rules behavior, you need to create two specific rules before creating this rule. For more details refer to [Migration from Page Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/page-rules-migration/).

[Create a cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/) to adjust cache level for any hostname containing `example.com`:

* **When incoming requests match**: Custom filter expression  
   * Using the Expression Builder:  
   `Hostname contains "example.com"`  
   * Using the Expression Editor:  
   `(http.host contains "example.com")`
* **Then**:  
   * **Cache eligibility**: Eligible for cache  
   * **Setting**: Cache key  
         * **Query string**: Ignore query string

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/examples/","name":"Examples"}},{"@type":"ListItem","position":6,"item":{"@id":"/cache/how-to/cache-rules/examples/cache-everything-ignore-query-strings/","name":"Cache Everything while ignoring query strings"}}]}
```

---

---
title: Cache TTL by status code
description: Cache TTL by status code
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache TTL by status code

Cache TTL by status code

Note

If you are migrating from Page Rules and you want to keep Page Rules behavior, you need to create two specific rules before creating this rule. For more details refer to [Migration from Page Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/page-rules-migration/).

[Create a cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/) to cache responses with status code between `200` and `599` for one day for any hostname containing `example.com`:

* **When incoming requests match**: Custom filter expression  
   * Using the Expression Builder:  
   `Hostname contains "example.com"`  
   * Using the Expression Editor:  
   `(http.host contains "example.com")`
* **Then**:  
   * **Cache eligibility**: Eligible for cache  
   * **Setting**: Edge TTL  
         * Use cache-control header if present, use default Cloudflare caching behavior if not  
         * **Status code TTL**:  
                  * **Scope**: _Range_  
                  * **From**: _200_  
                  * **To**: _599_  
                  * **Duration**: _1 day_

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/examples/","name":"Examples"}},{"@type":"ListItem","position":6,"item":{"@id":"/cache/how-to/cache-rules/examples/cache-ttl-by-status-code/","name":"Cache TTL by status code"}}]}
```

---

---
title: Custom Cache Key
description: Custom Cache Key
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Custom Cache Key

Custom Cache Key

Note

If you are migrating from Page Rules and you want to keep Page Rules behavior, you need to create two specific rules before creating this rule. For more details refer to [Migration from Page Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/page-rules-migration/).

[Create a cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/) to set a custom cache key for all query string parameters, for any hostname containing `example.com`:

* **When incoming requests match**: Custom filter expression  
   * Using the Expression Builder:  
   `Hostname contains "example.com"`  
   * Using the Expression Editor:  
   `(http.host contains "example.com")`
* **Then**:  
   * **Cache eligibility**: Eligible for cache  
   * **Setting**: Cache key  
         * **Query string**: All query string parameters

Refer to [cache keys](https://developers.cloudflare.com/cache/how-to/cache-keys/) for more information on possible settings when configuring a custom cache key.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/examples/","name":"Examples"}},{"@type":"ListItem","position":6,"item":{"@id":"/cache/how-to/cache-rules/examples/custom-cache-key/","name":"Custom Cache Key"}}]}
```

---

---
title: Edge Cache TTL
description: Edge Cache TTL
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Edge Cache TTL

Edge Cache TTL

[Create a cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/) to adjust edge cache TTL for caching resources on Cloudflare edge to one day, for any hostname containing `example.com`:

* **When incoming requests match**: Custom filter expression  
   * Using the Expression Builder:  
   `Hostname contains "example.com"`  
   * Using the Expression Editor:  
   `(http.host contains "example.com")`
* **Then**:  
   * **Cache eligibility**: Eligible for cache  
   * **Setting**: Edge TTL  
         * Ignore cache-control header and use this TTL  
                  * **Input time-to-live (TTL)**: _1 day_

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/examples/","name":"Examples"}},{"@type":"ListItem","position":6,"item":{"@id":"/cache/how-to/cache-rules/examples/edge-ttl/","name":"Edge Cache TTL"}}]}
```

---

---
title: Origin Cache Control
description: Origin Cache Control
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Origin Cache Control

Origin Cache Control

[Create a cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/) to determine edge cache behavior for any hostname containing `example.com`:

* **When incoming requests match**: Custom filter expression  
   * Using the Expression Builder:  
   `Hostname contains "example.com"`  
   * Using the Expression Editor:  
   `(http.host contains "example.com")`
* **Then**:  
   * **Cache eligibility**: Eligible for cache  
   * **Setting**: Origin Cache Control  
         * **Enable Origin Cache Control**: Off

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/examples/","name":"Examples"}},{"@type":"ListItem","position":6,"item":{"@id":"/cache/how-to/cache-rules/examples/origin-cache-control/","name":"Origin Cache Control"}}]}
```

---

---
title: Query String Sort
description: Query String Sort
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Query String Sort

Query String Sort

[Create a cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/) to sort query string parameters for caching purposes, for any hostname containing `example.com`:

* **When incoming requests match**: Custom filter expression  
   * Using the Expression Builder:  
   `Hostname contains "example.com"`  
   * Using the Expression Editor:  
   `(http.host contains "example.com")`
* **Then**:  
   * **Cache eligibility**: Eligible for cache  
   * **Setting**: Cache key  
         * **Sort query string**: On

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/examples/","name":"Examples"}},{"@type":"ListItem","position":6,"item":{"@id":"/cache/how-to/cache-rules/examples/query-string-sort/","name":"Query String Sort"}}]}
```

---

---
title: Respect Strong ETags
description: Respect Strong ETags
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Respect Strong ETags

Respect Strong ETags

[Create a cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/) to respect strong ETags for any hostname containing `example.com`:

* **When incoming requests match**: Custom filter expression  
   * Using the Expression Builder:  
   `Hostname contains "example.com"`  
   * Using the Expression Editor:  
   `(http.host contains "example.com")`
* **Then**:  
   * **Cache eligibility**: Eligible for cache  
   * **Setting**: Respect strong ETags  
         * **Use strong ETag headers**: On

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/examples/","name":"Examples"}},{"@type":"ListItem","position":6,"item":{"@id":"/cache/how-to/cache-rules/examples/respect-strong-etags/","name":"Respect Strong ETags"}}]}
```

---

---
title: Order and priority
description: How Cache Rules are ordered and which rule takes priority.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Order and priority

Cache rules affect requests differently from Page Rules. This is how they are applied:

1. Cache Rules are stackable. This means that multiple matching rules can be combined and applied to the same request. For example, if multiple cache rules match the same URL, then the features set in those cache rules will all be applied in order. If several matching rules set a value for the same setting, the value in the last matching rule wins. For an example of a similar scenario where multiple rules match, refer to the [Origin Rules FAQ](https://developers.cloudflare.com/rules/origin-rules/faq/#what-happens-if-more-than-one-origin-rule-matches-the-current-request).
2. For conflicting settings (for example, bypass cache versus eligible for cache), the last matching rule wins. For example, if cache rule #1 is set to cache everything on `example.com/images` and cache rule #2 is set to bypass cache on `example.com`, then cache will be bypassed for all URLs that match `example.com`, since rule #2 is the last matching rule.
3. If you have Page Rules implemented for caching on the same path, Cache Rules will take precedence by design.
4. Cache rules can be more specific than website-wide settings in the cache configuration tab, so they take precedence over website-wide settings on requests they match against. For example, if browser cache TTL is set to 4 hours for the entire website `example.com` and there is a cache rule matching requests with a path of `/feed` setting browser cache TTL to 10 seconds, the cache rule will override the website-wide setting for requests to `https://example.com/feed`.

## Execution order of Rules products

The execution order of Rules features is the following:

* [Single Redirects](https://developers.cloudflare.com/rules/url-forwarding/single-redirects/)
* [URL Rewrite Rules](https://developers.cloudflare.com/rules/transform/url-rewrite/)
* [Configuration Rules](https://developers.cloudflare.com/rules/configuration-rules/)
* [Origin Rules](https://developers.cloudflare.com/rules/origin-rules/)
* [Bulk Redirects](https://developers.cloudflare.com/rules/url-forwarding/bulk-redirects/)
* [Managed Transforms](https://developers.cloudflare.com/rules/transform/managed-transforms/)
* [Request Header Transform Rules](https://developers.cloudflare.com/rules/transform/request-header-modification/)
* [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/)
* [Snippets](https://developers.cloudflare.com/rules/snippets/)
* [Cloud Connector](https://developers.cloudflare.com/rules/cloud-connector/)

The different types of rules listed above will take precedence over [Page Rules](https://developers.cloudflare.com/rules/page-rules/). This means that Page Rules will be overridden if there is a match for both Page Rules and the Rules products listed above.

Generally speaking, for [non-terminating actions](https://developers.cloudflare.com/ruleset-engine/rules-language/actions/) the last change made by rules in the same [phase](https://developers.cloudflare.com/ruleset-engine/about/phases/) will win (later rules can overwrite changes done by previous rules). However, for terminating actions (_Block_, _Redirect_, or one of the challenge actions), rule evaluation will stop and the action will be executed immediately.

For example, if multiple rules with the _Redirect_ action match, Cloudflare will always use the URL redirect of the first rule that matches. Also, if you configure URL redirects using different Cloudflare products (Single Redirects and Bulk Redirects), the product executed first will apply, if there is a rule match (in this case, Single Redirects).

Refer to the [Phases list](https://developers.cloudflare.com/ruleset-engine/reference/phases-list/) for the product execution order.

Warning

Using Cloudflare challenges along with Rules features may cause challenge loops. Refer to [Rules troubleshooting](https://developers.cloudflare.com/rules/reference/troubleshooting/) for more information.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/order/","name":"Order and priority"}}]}
```

---

---
title: Migration from Page Rules
description: Migrate caching Page Rules to Cache Rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Migration from Page Rules

If you are migrating from Page Rules, there is a behavior change between Page Rules and Cache Rules.

When you create a new Cache Rule and select **Eligible for cache**, the Cache Everything feature is enabled by default. With Page Rules, you had to specifically enable the Cache Everything option.

To maintain the same behavior you had with Page Rules (that is, not enabling Cache Everything), you need to create these two specific rules in this order before creating any additional rules.

Multiple matching cache rules can be combined and applied to the same request. After rule 1 matches, Cloudflare will keep evaluating other cache rules checking for matches. For more information, refer to [Order and priority](https://developers.cloudflare.com/cache/how-to/cache-rules/order/).

## Rule 1

* [ Dashboard ](#tab-panel-6819)
* [ visual guide ](#tab-panel-6820)

1. Enter a rule name, for instance `bypass everything`.
2. In **When incoming requests match**, select **All incoming requests**.
3. Under **Then**, in the **Cache eligibility** section, select [Bypass cache](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#bypass-cache).

![Create rule to bypass cache](https://developers.cloudflare.com/_astro/first-rule.DCA_9a45_1jNULw.webp)

## Rule 2

* [ Dashboard ](#tab-panel-6821)
* [ visual guide ](#tab-panel-6822)

1. Enter a rule name, for instance `cache all default cacheable extensions`.
2. In **When incoming requests match**, select **Custom filter expression**.
3. Define the following rule:  
   * **Field**: `File extension`  
   * **Operator**: `is in`  
   * **Value**: `7z, avi, avif, apk, bin, bmp, bz2, class, css, csv, doc, docx, dmg, ejs, eot, eps, exe, flac, gif, gz, ico, iso, jar, jpg, jpeg, js, mid, midi, mkv, mp3, mp4, ogg, otf, pdf, pict, pls, png, ppt, pptx, ps, rar, svg, svgz, swf, tar, tif, tiff, ttf, webm, webp, woff, woff2, xls, xlsx, zip, zst`

If you prefer, you can select **Edit expression** and paste the following expression:

```

(http.request.uri.path.extension in {"7z" "avi" "avif" "apk" "bin" "bmp" "bz2" "class" "css" "csv" "doc" "docx" "dmg" "ejs" "eot" "eps" "exe" "flac" "gif" "gz" "ico" "iso" "jar" "jpg" "jpeg" "js" "mid" "midi" "mkv" "mp3" "mp4" "ogg" "otf" "pdf" "pict" "pls" "png" "ppt" "pptx" "ps" "rar" "svg" "svgz" "swf" "tar" "tif" "tiff" "ttf" "webm" "webp" "woff" "woff2" "xls" "xlsx" "zip" "zst"})


```

1. Under **Then**, in the **Cache eligibility** section, select [**Eligible for cache**](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#eligible-for-cache-settings).

![Create an eligible for cache rule](https://developers.cloudflare.com/_astro/second-rule.88NhnPNI_c13b4.webp)

Note

Remember to create the rules in the specified order: first, the `bypass everything` rule, and then the `cache all default cacheable file extensions` rule.

![Rules order](https://developers.cloudflare.com/_astro/rule-order.wNZiF99u_ZOuxf5.webp)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/page-rules-migration/","name":"Migration from Page Rules"}}]}
```

---

---
title: Available settings
description: Available settings for Cache Rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Available settings

These are the settings that you can configure when creating a cache rule.

## Fields

The fields available for Cache Rule matching expressions in the **Expression Builder** are:

* URI Full - `http.request.full_uri`
* URI - `http.request.uri`
* URI Path - `http.request.uri.path`
* URI Query String - `http.request.uri.query`
* Cookie - `http.cookie`
* Hostname - `http.host`
* Referer - `http.referer`
* SSL/HTTPS - `ssl`
* User Agent - `http.user_agent`
* X-Forwarded-For - `http.x_forwarded_for`
* Request Headers - `http.request.headers`
* Cookie value of - `http.request.cookies`
* File extension - `http.request.uri.path.extension`

If you select the [Edit expression](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/edit-expressions/#expression-editor) option, you can enter any of the [available fields](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/).

Note

[Single file purge](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-single-file/) is not compatible if you add other [fields](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/) than those listed, such as `ip.*` fields.

## Operators

The operators available for Cache Rule expressions are:

* wildcard
* strict wildcard
* equals
* does not equal
* contains
* does not contain
* matches regex
* does not match regex
* starts with
* ends with
* does not start with
* does not end with
* is in
* is not in
* is in list
* is not in list

Note

Not all operators are available for every selected field.

Note

The **is in list** and **is not in list** operators are available for the Hostname field on Enterprise plans. They allow you to match requests against [custom lists](https://developers.cloudflare.com/waf/tools/lists/custom-lists/) — for example, a hostname list containing all the domains you want to apply a particular caching configuration to. Refer to [Use lists in expressions](https://developers.cloudflare.com/waf/tools/lists/use-in-expressions/) for details on using lists in rule expressions.

## Cache eligibility

In **Cache eligibility**, you have the option to select **Bypass cache** if you want matching requests to not be cached, or **Eligible for cache** if you want Cloudflare to attempt to cache them.

### Bypass cache

When creating a cache rule, you have the option to select **Bypass cache** if you want matching incoming requests to not be cached. Alternatively, you can use [Development Mode](https://developers.cloudflare.com/cache/reference/development-mode/), if you want to bypass cache for shorter periods.

Note

When using Custom Cache Rules with a Bypass setting, the response header may return [DYNAMIC](https://developers.cloudflare.com/cache/concepts/cache-responses/#dynamic) rather than explicitly indicating a bypass. This occurs because the rule makes the content ineligible for caching, even if the origin response is otherwise cacheable.

### Eligible for cache settings

When you select **Eligible for cache**, you can change the configuration settings described below.

Note

If you use cache rules, image transformations, and zone versioning simultaneously, some settings may not be applied correctly.

#### Edge TTL

Edge Cache TTL refers to the maximum cache time-to-live (TTL), or how long an asset should be considered fresh or available to serve from Cloudflare’s cache in response to requests. This setting has three primary options:

* **Use cache control-header if present, bypass cache if not**: If a cache-control header is present on the response, follow its directives. If not, skip caching entirely.
* **Use cache-control header if present, use default Cloudflare caching behavior if not**: If a cache-control header is present on the response, follow its directives. If not, cache in accordance with our [default edge TTL settings](https://developers.cloudflare.com/cache/how-to/configure-cache-status-code/#edge-ttl).
* **Ignore cache-control header and use this TTL**: Completely ignore any cache-control header on the response and instead cache the response for a duration specified in the timing dropdown.

Additionally, you can select how long you would like a particular matching status code's content to be cached in Cloudflare's global network. In **Status Code TTL** section you can define the TTL duration for one or more status codes of responses from the origin server. This setting can be applied to a _Single code_ status code, to a _Greater than or equal_ or _Less than or equal_ status code, or to a _Range_ of status codes. Status code TTLs are similar to **Ignore cache-control header and use this TTL** in that the cache-control header on the response will be ignored in favor of the TTL specified by the cache rule. For more information, refer to [Status code TTL](https://developers.cloudflare.com/cache/how-to/configure-cache-status-code/).

API information

API configuration object name: `"edge_ttl"`.

| API values          | Configuration                                                                                                                                                    |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| respect\_origin     | Use cache-control header if present, use default [Cloudflare caching behavior](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/) if not. |
| override\_origin    | Ignore cache-control header and use this TTL.                                                                                                                    |
| bypass\_by\_default | Use cache control-header if present, bypass cache if not.                                                                                                        |

API configuration example

```

"action_parameters": {

    "cache": true,

    "edge_ttl": {

        "status_code_ttl": [

            {

                "status_code_range": {

                    "to": 299

                },

                "value": 86400

            },

            {

                "status_code_range": {

                    "from": 300,

                    "to": 499

                },

                "value": 0  // no-cache

            },

            {

                "status_code_range": {

                    "from": 500

                },

                "value": -1  // no-store

            }

        ],

        "mode": "respect_origin"

    }

}


```

Refer to [Create a cache rule via API](https://developers.cloudflare.com/cache/how-to/cache-rules/create-api/#example-requests) for complete API examples.

#### Browser TTL

Browser TTL refers to the maximum cache time-to-live (TTL) that an asset should be considered available to serve from the browser’s cache.

Select if you want to **Bypass cache**, **Respect origin**, or **Override origin**. If you wish to override the browser TTL value, define how long resources cached by client browsers will remain valid from the dropdown menu. For more information, refer to [Browser Cache TTL](https://developers.cloudflare.com/cache/how-to/edge-browser-cache-ttl/#browser-cache-ttl).

API information

API configuration object name: `"browser_ttl"`.

API values for the `"mode"` property: `"respect_origin"`, `"override_origin"`, `"bypass_by_default"`.   

API values for the `"default"` property (integer): values available depend on your plan. Refer to [Browser Cache TTL](https://developers.cloudflare.com/cache/how-to/edge-browser-cache-ttl/#browser-cache-ttl).

API configuration example

```

"action_parameters": {

  "cache": true,

  "browser_ttl" : {

    "mode": "override_origin",

    "default": 1000

  }

}


```

Refer to [Create a cache rule via API](https://developers.cloudflare.com/cache/how-to/cache-rules/create-api/#example-requests) for complete API examples.

#### Cache Key

Cache keys refer to the criteria that Cloudflare uses to determine how to store resources in our cache. Customizing the Cache Key allows you to determine how Cloudflare can reuse particular cache entries across requests or share the cache entries for more granularity for end users.

Define the request components used to define a [custom Cache Key](https://developers.cloudflare.com/cache/how-to/cache-keys/), customizing the following options:

* You can switch on or off [Cache deception armor](https://developers.cloudflare.com/cache/cache-security/cache-deception-armor/), [Cache by device type](https://developers.cloudflare.com/automatic-platform-optimization/reference/cache-device-type/), and [Sort query string](https://developers.cloudflare.com/cache/how-to/cache-keys/#query-string).

Enterprise customers have these additional options for custom Cache Keys:

* In the **Query string** section, you can select **All query string parameters**, **All query string parameters except** and enter an exception, **No query parameters except** and enter the parameters, or **Ignore query string** (also available for Pay-as-you-go customers).
* In the **Headers** section, you can specify header names along with their values. For custom headers, values are optional; however, for the following restricted headers, you must include one to three specific values:  
   * `accept`  
   * `accept-charset`  
   * `accept-encoding`  
   * `accept-datetime`  
   * `accept-language`  
   * `referer`  
   * `user-agent`  
To check for a header's presence without including its value, use the **Check presence of** option. You can also choose whether to **Include origin header**.
* In the **Cookie** section, you can include cookie names and their values, and check for the presence of another cookie.
* In the **Host** section, you can select **Use original host** and **Resolved host**. In the **User** section, you can select **Device type**, **Country**, and **Language**. Using **Resolved host** means the Cache Key will contain whatever hostname was used to resolve the origin IP which can be different depending on whether the [resolve override](https://developers.cloudflare.com/rules/origin-rules/features/#dns-record) feature is on or not.

Note

When [URL normalization](https://developers.cloudflare.com/rules/normalization/) is enabled, we recommend also enabling [Normalize URLs to origin](https://developers.cloudflare.com/rules/normalization/manage/), especially if you are setting custom Cache Keys or using cache by device type, which also modifies the Cache Key. This helps ensure the URL in the Cache Key matches the URL sent to the origin, preventing cache poisoning and ensuring consistent behavior.

API information

API configuration object name: `"cache_key"`.

API values: `"ignore_query_strings_order"`, `"cache_deception_armor"`, `"cache_by_device_type"`, `"custom_key"` (`"header"`, `"cookie"`, `"host"`, `"query_string"`, `"user"`).

API configuration example

```

"action_parameters": {

  "cache": true,

  "cache_key": {

    "ignore_query_strings_order": true,

    "cache_deception_armor": true,

    "custom_key": {

      "query_string": {

        "include": [

          "*"

        ]

      },

      "header": {

        "include": [

          "header1"

        ],

        "check_presence": [

          "header_1"

        ],

        "contains": {

          "accept-encoding": ["br", "zstd"]

        }

      },

      "cookie": {

        "include": [

          "cookieName1"

        ],

        "check_presence": [

          "cookie_1"

        ]

      },

      "user": {

        "device_type": true,

        "geo": true,

        "lang": true

      },

      "host": {

        "resolved": false

      }

    }

  }

}


```

Refer to [Create a cache rule via API](https://developers.cloudflare.com/cache/how-to/cache-rules/create-api/#example-requests) for complete API examples.

#### Cache Reserve Eligibility

Cache Reserve eligibility allows you to specify which website resources should be eligible for our persistent cache called [Cache Reserve](https://developers.cloudflare.com/cache/advanced-configuration/cache-reserve/). If the request matches and also meets [eligibility criteria](https://developers.cloudflare.com/cache/advanced-configuration/cache-reserve/#cache-reserve-asset-eligibility), Cloudflare will write the resource to cache reserve. This requires an add-on cache reserve plan.

This rule can also be used to specify Cache Reserve eligibility for website resources based on their size. For example, by specifying that all assets which are eligible be 100 MB and above, Cloudflare will look for eligible assets at or above 100 MB for Cache Reserve eligibility and only persistently store those assets.

Note

Cloudflare will still enforce the plan-based [cacheable file limits](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#customization-options-and-limits) when using this configuration.

API information

API configuration object name: `"cache_reserve"`.

API property name for enabling Cache Reserve: `"eligible"` (boolean).

API configuration example

```

"action_parameters": {

  "cache": true

  "cache_reserve": {

    "eligible": true,

    "minimum_file_size": 100000

  }

}


```

Note

If `minimum_file_size` is omitted and `eligible` is true, Cloudflare will use 0 bytes by default.

Refer to [Create a cache rule via API](https://developers.cloudflare.com/cache/how-to/cache-rules/create-api/#example-requests) for complete API examples.

#### Caching on Port (Enterprise-only)

Cloudflare supports several [network ports](https://developers.cloudflare.com/fundamentals/reference/network-ports/#network-ports-compatible-with-cloudflares-proxy) by default, like 80 or 443\. Some ports, traditionally admin ports, are supported but have caching disabled as they are used to manage sensitive information that should be ineligible for cache. Enterprise customers wanting to enable caching on these admin ports can cache on these ports by entering their desired port.

Note

Cloudflare supports many ports by default and will cache on them without needing this rule to be configured. For ports that Cloudflare supports, but for which caching is disabled, use this rule.

API information

API configuration property name: `"additional_cacheable_ports"` (array of integer values).

API configuration example

```

"action_parameters": {

    "cache": true

    "additional_cacheable_ports": [8443, 8080]

  }

}


```

Refer to [Create a cache rule via API](https://developers.cloudflare.com/cache/how-to/cache-rules/create-api/#example-requests) for complete API examples.

#### Proxy Read Timeout (Enterprise-only)

Defines a timeout value between two successive read operations to your origin server. The default value can be found in the [Connection limits](https://developers.cloudflare.com/fundamentals/reference/connection-limits/) table. If you are attempting to reduce [HTTP 524](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-524/) errors because of timeouts from an origin server, try increasing this timeout value using the API endpoint below.

API information

API configuration property name: `"read_timeout"` (integer).

API configuration example

```

"action_parameters": {

  "cache": true,

  "read_timeout": 900

}


```

Refer to [Create a cache rule via API](https://developers.cloudflare.com/cache/how-to/cache-rules/create-api/#example-requests) for complete API examples.

#### Serve stale content while revalidating

Defines if Cloudflare will serve stale content while updating the latest content from the origin server. If serving stale content is disabled, Cloudflare will not serve stale content while getting the latest content from the origin.

API information

API configuration property name: `"serve_stale"` \> `"disable_stale_while_updating"` (boolean).

API configuration example

```

"action_parameters": {

  "cache": true,

  "serve_stale": {

    "disable_stale_while_updating": true

  }

}


```

Refer to [Create a cache rule via API](https://developers.cloudflare.com/cache/how-to/cache-rules/create-api/#example-requests) for complete API examples.

#### Respect Strong ETags

Turn on or off byte-for-byte equivalency checks between the Cloudflare cache and the origin server. When enabled, Cloudflare will use [strong ETag](https://developers.cloudflare.com/cache/reference/etag-headers/#strong-etags) header validation to ensure that resources in the Cloudflare cache and on the origin server are byte-for-byte identical. If disabled, Cloudflare converts ETag headers into [weak ETag](https://developers.cloudflare.com/cache/reference/etag-headers/#weak-etags) headers.

API information

API configuration property name: `"respect_strong_etags"` (boolean).

API configuration example

```

"action_parameters": {

  "cache": true,

  "respect_strong_etags": true

}


```

Refer to [Create a cache rule via API](https://developers.cloudflare.com/cache/how-to/cache-rules/create-api/#example-requests) for complete API examples.

#### Origin error page pass-through

Turn on or off Cloudflare error pages generated from error HTTP status codes sent from the origin server. If enabled, this setting enables the use of error pages issued by the origin.

API information

API configuration property name: `"origin_error_page_passthru"` (boolean).

API configuration example

```

"action_parameters": {

  "cache": true,

  "origin_error_page_passthru": true

}


```

Refer to [Create a cache rule via API](https://developers.cloudflare.com/cache/how-to/cache-rules/create-api/#example-requests) for complete API examples.

#### Origin Cache Control (Enterprise-only)

When this option is enabled, Cloudflare will aim to strictly adhere to [RFC 7234 ↗](https://datatracker.ietf.org/doc/html/rfc7234). Enterprise customers have the ability to select if Cloudflare will adhere to this behavior. Free, Pro, and Business customers have this option enabled by default and cannot disable it.

API information

API configuration property name: `"origin_cache_control"` (boolean).

API configuration example

```

"action_parameters": {

  "cache": true

  "origin_cache_control": true

}


```

Refer to [Create a cache rule via API](https://developers.cloudflare.com/cache/how-to/cache-rules/create-api/#example-requests) for complete API examples.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/settings/","name":"Available settings"}}]}
```

---

---
title: Terraform example
description: Create Cache Rules using Terraform.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Terraform example

The following example defines a single cache rule for a zone using Terraform. The rule configures several cache settings and sets a custom cache key for incoming requests addressed at `example.net`.

Terraform `cloudflare_ruleset` resource

```

# Cache rule configuring cache settings and defining custom cache keys

resource "cloudflare_ruleset" "cache_rules_example" {

  zone_id     = "<ZONE_ID>"

  name        = "Set cache settings"

  description = "Set cache settings for incoming requests"

  kind        = "zone"

  phase       = "http_request_cache_settings"


  rules {

    ref         = "cache_settings_custom_cache_key"

    description = "Set cache settings and custom cache key for example.net"

    expression  = "(http.host eq \"example.net\")"

    action      = "set_cache_settings"

    action_parameters {

      edge_ttl {

        mode    = "override_origin"

        default = 60

        status_code_ttl {

          status_code = 200

          value       = 50

        }

        status_code_ttl {

          status_code_range {

            from = 201

            to   = 300

          }

          value = 30

        }

      }

      browser_ttl {

        mode = "respect_origin"

      }

      serve_stale {

        disable_stale_while_updating = true

      }

      respect_strong_etags = true

      cache_key {

        ignore_query_strings_order = false

        cache_deception_armor      = true

        custom_key {

          query_string {

            exclude {

              all = true

            }

          }

          header {

            include        = ["habc", "hdef"]

            check_presence = ["habc_t", "hdef_t"]

            exclude_origin = true

          }

          cookie {

            include        = ["cabc", "cdef"]

            check_presence = ["cabc_t", "cdef_t"]

          }

          user {

            device_type = true

            geo         = false

          }

          host {

            resolved = true

          }

        }

      }

      origin_error_page_passthru = false

    }

  }

}


```

Use the `ref` field to get stable rule IDs across updates when using Terraform. Adding this field prevents Terraform from recreating the rule on changes. For more information, refer to [Troubleshooting](https://developers.cloudflare.com/terraform/troubleshooting/rule-id-changes/#how-to-keep-the-same-rule-id-between-modifications) in the Terraform documentation.

For additional guidance on using Terraform with Cloudflare, refer to [Terraform](https://developers.cloudflare.com/terraform/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/cache-rules/","name":"Cache Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/cache-rules/terraform-example/","name":"Terraform example"}}]}
```

---

---
title: Cache by status code
description: Cache responses based on origin HTTP status codes.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache by status code

Customers can set cache time-to-live (TTL) based on the response status from the origin web server. Cache TTL refers to the duration of a resource in the Cloudflare network before being marked as `STALE` or discarded from cache. Status codes are returned by a resource's origin.

Setting cache TTL based on response status overrides the [default cache behavior (standard caching)](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/) for static files and overrides cache instructions sent by the origin web server. To cache non-static assets, set a [Cache Level of Cache Everything using a Cache Rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-api/#example-requests). Setting `no-store` **Cache-Control** or a low TTL (using `max-age`/`s-maxage`) increases requests to origin web servers and decreases performance.

## Caching limits

The maximum caching limit for Free, Pro, and Business customers is 512 MB per file, and the maximum caching limit for Enterprise customers is 5 GB per file. If you need to raise the limits, contact your Customer Success Manager.

## Edge TTL

By default, Cloudflare caches certain HTTP response codes with the following Edge Cache TTL when a `cache-control` directive or `expires` response header are not present.

| HTTP status code | Default TTL |
| ---------------- | ----------- |
| 200, 206, 301    | 120m        |
| 302, 303         | 20m         |
| 404, 410         | 3m          |

All other status codes are not cached by default.

## Set cache TTL by response status via the Cloudflare dashboard

To set cache TTL by response status, [create a Cache Rule](https://developers.cloudflare.com/cache/how-to/cache-rules/) for [**Cache TTL by status code**](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#edge-ttl).

## Set cache TTL by response status via the Cloudflare API

Request

```

curl --request PUT \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/rulesets/{ruleset_id}" \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "rules": [

    {

      "expression": "(http.host eq \"www.example.com\")",

      "description": "set cache TTL by response status",

      "action": "set_cache_settings",

      "action_parameters": {

        "cache": true,

        "edge_ttl": {

          "status_code_ttl": [

            {

              "status_code_range": {

                "to": 299

              },

              "value": 86400

            },

            {

              "status_code_range": {

                "from": 300,

                "to": 499

              },

              "value": 0  // no-cache

            },

            {

              "status_code_range": {

                "from": 500

              },

              "value": -1  // no-store

            }

          ],

          "mode": "respect_origin"

        }

      }

    }

  ]

}'


```

### Syntax

Provide a JSON object containing status codes and their corresponding TTLs. Each key-value pair in the cache TTL by status cache rule has the following syntax:

* `status_code`: An integer value such as 200 or 500\. `status_code` matches the exact status code from the origin web server. Valid status codes are between 100-999.
* `status_code_range`: Integer values for `from` and `to`. `status_code_range` matches any status code from the origin web server within the specified range.
* `value`: An integer value that defines the duration an asset is valid in seconds or one of the following strings: `no-store` (equivalent to `-1`), `no-cache` (equivalent to `0`).

## Set cache TTL by response status via a Cloudflare Worker

The **cacheTtlByStatus** option is a version of the **cacheTtl** feature that designates a cache TTL for a request’s response status code (for example, `{ "200-299": 86400, 404: 1, "500-599": 0 }`).

## TTL handling for 304 and 200 status codes

1. If a TTL is not explicitly set for status code `304`, we automatically set it to match the TTL of status code `200` (if the user has defined one for `200`).
2. If a user explicitly sets a different TTL for `304` than for `200`, the following behavior will occur:
* When a `200` response is received, the asset is cached with the TTL specified for status `200`.
* Once the asset expires and we revalidate with the origin, if the origin returns a `304`, the cache TTL is updated to the value set for `304`.

For example, if a user specifies a TTL of one hour for status `200` and 0 seconds (cache and always revalidate) for status `304`, the asset will be cached for 1 hour. After it expires, we revalidate with the origin. If the origin returns a `304`, each subsequent request will trigger revalidation. If the origin continues to return `304`, this cycle will persist.

This behavior is likely undesirable unless the user has a specific use case. Therefore, users should ensure that the TTL for `304` matches the TTL for `200` unless they intentionally require this behavior.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/configure-cache-status-code/","name":"Cache by status code"}}]}
```

---

---
title: Edge and Browser Cache TTL
description: Configure edge and browser cache TTL for your resources.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Edge and Browser Cache TTL

## Edge Cache TTL

Edge Cache TTL (Time to Live) specifies the maximum time to cache a resource in the Cloudflare global network. Edge Cache TTL is not visible in response headers and the minimum Edge Cache TTL depends on plan type.

| Free                   | Pro     | Business | Enterprise |          |
| ---------------------- | ------- | -------- | ---------- | -------- |
| Availability           | Yes     | Yes      | Yes        | Yes      |
| Minimum Edge Cache TTL | 2 hours | 1 hour   | 1 second   | 1 second |

For more information on how to set up Edge Cache TTL, refer to [Cache rules](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#edge-ttl).

## Browser Cache TTL

The Browser Cache TTL sets the expiration for resources cached in a visitor’s browser. By default, Cloudflare honors the cache expiration set in your `Expires` and `Cache-Control` headers but overrides those headers if:

* The value of the `Expires` or `Cache-Control` header from the origin web server is less than the Browser Cache TTL Cloudflare setting.
* The origin web server does not send a `Cache-Control` or an `Expires` header.

Unless specifically set in a cache rule, Cloudflare does not override or insert `Cache-Control` headers if you set **Browser Cache TTL** to **Respect Existing Headers**.

Note

* Setting high Browser Cache TTL values means that the assets will be cached for a long time by users’ browsers.
* If you modify cached assets, the new assets may not be displayed to repeat visitors before the Browser Cache TTL expires.
* Purging Cloudflare’s cache does not affect assets stored by a visitor’s browser.

| Free                                   | Pro       | Business  | Enterprise |            |
| -------------------------------------- | --------- | --------- | ---------- | ---------- |
| Availability                           | Yes       | Yes       | Yes        | Yes        |
| Minimum Browser Cache TTL (Page Rules) | 2 minutes | 2 minutes | 2 minutes  | 30 seconds |
| Minimum Browser Cache TTL              | 1 second  | 1 second  | 1 second   | 1 second   |
| Default Browser Cache TTL              | 4 hours   | 4 hours   | 4 hours    | 4 hours    |

For more information on setting the Browser Cache TTL, refer to [Set Browser Cache TTL](https://developers.cloudflare.com/cache/how-to/edge-browser-cache-ttl/set-browser-ttl/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/edge-browser-cache-ttl/","name":"Edge and Browser Cache TTL"}}]}
```

---

---
title: Set Browser Cache TTL
description: Set how long browsers cache resources from your site.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Set Browser Cache TTL

Specify a time for a visitor’s Browser Cache TTL to accelerate the page load for repeat visitors to your website. To configure cache duration within Cloudflare’s data centers, refer to [Edge Cache TTL](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#edge-ttl).

By default, Cloudflare honors the cache expiration set in your `Expires` and `Cache-Control` headers. Cloudflare overrides any `Cache-Control` or `Expires` headers with values set via the **Browser Cache TTL** option under **Caching** on your dashboard if:

* The value of the `Cache-Control` header from the origin web server is less than the **Browser Cache TTL** setting. This means that **Browser cache TTL** value needs to be higher than origin `max-age`.
* The origin web server does not send a `Cache-Control` or an `Expires` header.

Unless specifically set in a [Cache Rule](https://developers.cloudflare.com/cache/how-to/cache-rules/), Cloudflare does not override or insert `Cache-Control` headers if you set **Browser Cache TTL** to **Respect Existing Headers**.

Nevertheless, the value you set via Cache Rule will be ignored if `Cache-Control: max-age` is higher. In other words, you can override to make browsers cache longer than Cloudflare's edge but not less.

## Set Browser Cache TTL

Note

If you modify cached assets, the new asset is not displayed to repeat visitors before the Browser Cache TTL duration. [Purging Cloudflare’s cache](https://developers.cloudflare.com/cache/how-to/purge-cache/) does not affect assets cached in a visitor’s browser.

1. In the Cloudflare dashboard, go to the **Caching** page.  
[ Go to **Configuration** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/configuration)
2. Under **Browser Cache TTL**, select the desired cache expiration time from the drop-down menu.

The **Respect Existing Headers** option tells Cloudflare to honor the settings in the `Cache-Control` headers from your origin web server.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/edge-browser-cache-ttl/","name":"Edge and Browser Cache TTL"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/edge-browser-cache-ttl/set-browser-ttl/","name":"Set Browser Cache TTL"}}]}
```

---

---
title: Purge cache
description: Remove cached content from Cloudflare edge servers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Purge cache

Cloudflare's Instant Purge ensures that updates to your content are reflected immediately. Multiple options are available for purging content, with single-file cache purging (purge by URL) being the recommended method. However, the following additional options are also available:

* [ ​Purge by single-file ](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-single-file/)
* [ ​Purge everything ](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-everything/)
* [ Purge cache by cache-tags ](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-tags/)
* [ ​Purge cache by hostname ](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-hostname/)
* [ ​Purge cache by prefix (URL) ](https://developers.cloudflare.com/cache/how-to/purge-cache/purge%5Fby%5Fprefix/)
* [ Purge cache key resources ](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-cache-key/)
* [ P​urge varied images ](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-varied-images/)
* [ Purge zone versions via API ](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-zone-versions/)

Note

If versioning is active on your zone and multiple environments are configured, you can select the specific environment you want to purge. For more details, refer to the [Version Management](https://developers.cloudflare.com/version-management/) documentation.

## Availability and limits

| Free          | Pro                                              | Business                                         | Enterprise                                       |                                                  |
| ------------- | ------------------------------------------------ | ------------------------------------------------ | ------------------------------------------------ | ------------------------------------------------ |
| Availability  | Yes                                              | Yes                                              | Yes                                              | Yes                                              |
| Purge options | URL, Hostname, Tag, Prefix, and Purge Everything | URL, Hostname, Tag, Prefix, and Purge Everything | URL, Hostname, Tag, Prefix, and Purge Everything | URL, Hostname, Tag, Prefix, and Purge Everything |

### Hostname, tag, prefix URL, and purge everything limits

The current purge limits are applied per **account**:

| Free                       | Pro                   | Business              | Enterprise             |                        |
| -------------------------- | --------------------- | --------------------- | ---------------------- | ---------------------- |
| Requests                   | 5 requests per minute | 5 requests per second | 10 requests per second | 50 requests per second |
| Bucket size                | 25                    | 25                    | 50                     | 500                    |
| Max operations per request | 100                   | 100                   | 100                    | 100                    |

If your account includes zones with different Cloudflare plans, the above limits are shared between all the zones with the same plan. For example, all the zones in your account with a Pro plan will share the limits for the Pro plan, and all the zones in your account with a Business plan will share the limits for the Business plan.

### Single-file purge limits

The current purge limits are applied per **account**:

| Free                       | Pro                 | Business             | Enterprise           |                      |
| -------------------------- | ------------------- | -------------------- | -------------------- | -------------------- |
| URLs                       | 800 URLs per second | 1500 URLs per second | 1500 URLs per second | 3000 URLs per second |
| Max operations per request | 100                 | 100                  | 100                  | 500                  |

If your account includes zones with different Cloudflare plans, the above limits are shared between all the zones with the same plan. For example, all the zones in your account with a Pro plan will share the limits for the Pro plan, and all the zones in your account with a Business plan will share the limits for the Business plan.

Note that the thresholds for URLs are calculated using a moving average.

### Token bucket rate limiting

Cloudflare uses token bucket rate limiting to limit the number of purge requests flowing through the system at any given time, ensuring a steady and manageable flow.

Each account tier has a defined request rate (for example, Free: 5 requests per minute, Business: 10 requests per second), and requests are only allowed if there are available tokens in the bucket. Tokens refill at a consistent rate, but each bucket has a maximum capacity (for example, Free: 25 tokens, Enterprise: 500 tokens), allowing short bursts of requests if tokens have accumulated.

If the bucket is empty, further requests must wait until new tokens are added. This system maintains fair usage while allowing occasional bursts within the bucket's capacity.

If you are an Enterprise customer and you need more operations, reach out to your account team for support.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/purge-cache/","name":"Purge cache"}}]}
```

---

---
title: ​Purge cache by prefix (URL)
description: Purge cached resources by URL prefix.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# ​Purge cache by prefix (URL)

You can instantly purge their cache by URL prefix or path separators in their URL. For an example URL like `https://www.example.com/foo/bar/baz/qux.jpg`, valid purge requests include:

* `www.example.com`
* `www.example.com/foo`
* `www.example.com/foo/bar`
* `www.example.com/foo/bar/baz`
* `www.example.com/foo/bar/baz/qux.jpg`

Purging by prefix is useful in different scenarios, such as:

* Purging everything within a directory.
* Increasing control over cached objects in a path.
* Simplifying the number of purge calls sent.
1. In the Cloudflare dashboard, go to the **Configuration** page.  
[ Go to **Configuration** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/configuration)
2. Under **Purge Cache**, select **Custom Purge**. The **Custom Purge** window appears.
3. Under **Purge by**, select **Prefix**.
4. Follow the syntax instructions.  
   * One prefix per line.  
   * Maximum 30 prefixes per API call.
5. Enter the appropriate value(s) in the text field using the format shown in the example.
6. Select **Purge**.

For information on rate limits, refer to the [Availability and limits](https://developers.cloudflare.com/cache/how-to/purge-cache/#availability-and-limits) section.

Warning

If you have a [Transform Rule](https://developers.cloudflare.com/rules/transform/) in place that is modifying part of a URL path, you must use the post-transformed (origin) URL when performing a prefix purge so that purge can take effect.

## Resulting cache status

Purging by prefix deletes the resource, causing `CF-Cache-Status` header to show [MISS](https://developers.cloudflare.com/cache/concepts/cache-responses/#miss) for the subsequent request.

If [tiered cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) is used, purging by prefix may return `EXPIRED`, as the lower tier tries to revalidate with the upper tier to reduce load on the latter. Depending on whether the upper tier has the resource or not, and whether the end user is reaching the lower tier or the upper tier, `EXPIRED` or `MISS` are returned.

## Limitations

There are several limitations regarding purge by prefix:

* Path separators are limited to 31 for a prefix `(example.com/a/b/c/d/e/f/g/h/i/j/k/l/m…)`.
* Purge requests are limited to 30 prefixes per request.
* [Purge rate-limits apply](https://developers.cloudflare.com/api/resources/cache/methods/purge/).
* URI query strings & fragments cannot purge by prefix:  
   * `www.example.com/foo?a=b` (query string)  
   * `www.example.com/foo#bar` (fragment)

Warning

Because purge by prefix purges a directory, any URI for a resource within the purged directory is purged regardless of query string or fragment (though fragments are not generally sent by browsers). Purge by prefix rules do not accept fragments and query strings.

Example: If you purge `foo.com/bar`, any asset that starts with `foo.com/bar` will be purged, for example, `foo.com/bar/baz`, `foo.com/bar?good=bad`, etc. and purging `foo.com/bar?good=bad` itself will not work.

## Purge by prefix normalization

Using purge by prefix normalization, when a purge by prefix request comes into Cloudflare for a normalized URL path, the purge service respects the [URL normalization](https://developers.cloudflare.com/rules/normalization/) and purges the normalized URL.

### How does URL Normalization work

Take the following website as an example: `https://cloudflare.com/انشاء-موقع-الكتروني/img_1.jpg`. The table below shows you how Cloudflare’s cache views these paths with [normalization on/off](https://developers.cloudflare.com/rules/normalization/).

| Request from visitor to EDGE                                                                                                                                                                                                                                                                | What Cloudflare cache sees with Normalize Incoming URLs ON                                                                                                                                                                                                                                  | What Cloudflare cache sees with Normalize Incoming URLs OFF                                                                                                                                                                                                                                 | |  [https://cloudflare.com/انشاء-موقع-الكتروني/img\_1.jpg ↗](https://cloudflare.com/%D8%A7%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D9%88%D9%82%D8%B9-%D8%A7%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A/img%5F1.jpg) | [https://cloudflare.com/%D8%A7%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D9%88%D9%82%D8%B9-%D8%A7%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A/img\_1.jpg ↗](https://cloudflare.com/%D8%A7%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D9%88%D9%82%D8%B9-%D8%A7%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A/img%5F1.jpg) | [https://cloudflare.com/انشاء-موقع-الكتروني/img\_1.jpg ↗](https://cloudflare.com/%D8%A7%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D9%88%D9%82%D8%B9-%D8%A7%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A/img%5F1.jpg) |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [https://cloudflare.com/%D8%A7%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D9%88%D9%82%D8%B9-%D8%A7%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A/img\_1.jpg ↗](https://cloudflare.com/%D8%A7%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D9%88%D9%82%D8%B9-%D8%A7%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A/img%5F1.jpg) | [https://cloudflare.com/%D8%A7%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D9%88%D9%82%D8%B9-%D8%A7%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A/img\_1.jpg ↗](https://cloudflare.com/%D8%A7%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D9%88%D9%82%D8%B9-%D8%A7%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A/img%5F1.jpg) | [https://cloudflare.com/%D8%A7%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D9%88%D9%82%D8%B9-%D8%A7%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A/img\_1.jpg ↗](https://cloudflare.com/%D8%A7%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D9%88%D9%82%D8%B9-%D8%A7%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A/img%5F1.jpg) |                                                                                                                                                                                                           |                                                                                                                                                                                                                                                                                             |                                                                                                                                                                                                        |
| [https://cloudflare.com/hello/img\_1.jpg ↗](https://cloudflare.com/hello/img%5F1.jpg)                                                                                                                                                                                                       | [https://cloudflare.com/hello/img\_1.jpg ↗](https://cloudflare.com/hello/img%5F1.jpg)                                                                                                                                                                                                       | [https://cloudflare.com/hello/img\_1.jpg ↗](https://cloudflare.com/hello/img%5F1.jpg)                                                                                                                                                                                                       |                                                                                                                                                                                                           |                                                                                                                                                                                                                                                                                             |                                                                                                                                                                                                        |

As shown above, with URL normalization **ON**, visitors to the two URLs, `https://cloudflare.com/%D8%A7%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D9%88%D9%82%D8%B9-%D8%A7%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A/img_1.jpg` and `https://cloudflare.com/انشاء-موقع-الكتروني/img_1.jpg`, will be served the same cached asset. Purging `https://cloudflare.com/%D8%A7%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D9%88%D9%82%D8%B9-%D8%A7%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A/img_1.jpg` will instantly purge that asset for both visitors.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/purge-cache/","name":"Purge cache"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/purge-cache/purge_by_prefix/","name":"​Purge cache by prefix (URL)"}}]}
```

---

---
title: ​Purge cache by hostname
description: Purge all cached resources for a specific hostname.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# ​Purge cache by hostname

Purging by hostname means that all assets at URLs with a host that matches one of the provided values will be instantly purged from the cache.

1. In the Cloudflare dashboard, go to the **Configuration** page.  
[ Go to **Configuration** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/configuration)
2. Under **Purge Cache**, select **Custom Purge**. The **Custom Purge** window appears.
3. Under **Purge by**, select **Hostname**.
4. Follow the syntax instructions:  
   * One hostname per line.  
   * Separated by commas.  
   * You can purge up to 30 hostnames at a time.
5. Enter the appropriate value(s) in the text field using the format shown in the example.
6. Select **Purge**.

For information on rate limits, refer to the [Availability and limits](https://developers.cloudflare.com/cache/how-to/purge-cache/#availability-and-limits) section.

## Resulting cache status

Purging by hostname deletes the resource, resulting in the `CF-Cache-Status` header being set to [MISS](https://developers.cloudflare.com/cache/concepts/cache-responses/#miss) for subsequent requests.

If [tiered cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) is used, purging by hostname may return `EXPIRED`, as the lower tier tries to revalidate with the upper tier to reduce load on the latter. Depending on whether the upper tier has the resource or not, and whether the end user is reaching the lower tier or the upper tier, `EXPIRED` or `MISS` are returned.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/purge-cache/","name":"Purge cache"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/purge-cache/purge-by-hostname/","name":"​Purge cache by hostname"}}]}
```

---

---
title: ​Purge by single-file
description: Purge a single cached file by URL.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# ​Purge by single-file

With purge by single-file, cached resources are instantly removed from the stored assets in your Content Delivery Network (CDN) across all data centers. New requests for the purged asset receive the latest version from your origin web server and add it back to your CDN cache within the specific Cloudflare data center that served the request.

For information on single-file purge rate limits, refer to the [limits](https://developers.cloudflare.com/cache/how-to/purge-cache/#single-file-purge-limits) section.

A single-file purge performed through your Cloudflare dashboard does not clear objects that contain any of the following:

* [Custom cache keys](https://developers.cloudflare.com/cache/how-to/cache-keys/)
* [Origin header ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Origin)
* Any of these request headers:  
   * `X-Forwarded-Host`  
   * `X-Host`  
   * `X-Forwarded-Scheme`  
   * `X-Original-URL`  
   * `X-Rewrite-URL`  
   * `Forwarded`

You can purge objects with these characteristics using an API call to ([purge files by URL](https://developers.cloudflare.com/api/resources/cache/methods/purge/)). In the data/header section of the API call, you must include all headers and cache keys contained in the cached resource, along with their matching values.

Warning

Always use UTF-8 encoded URLs for single-file cache purges. Wildcards are not supported on single file purge, and you must use purge by hostname, prefix, or implement cache tags as an alternative solution.

1. In the Cloudflare dashboard, go to the **Configuration** page.  
[ Go to **Configuration** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/configuration)
2. Under **Purge Cache**, select **Custom Purge**. The **Custom Purge** window appears.
3. Under **Purge by**, select **URL**.
4. Enter the appropriate value(s) in the text field using the format shown in the example. Be aware that the host part of the URL is not case-sensitive, meaning it will always be converted to lowercase according to RFC standards. However, the path portion is case-sensitive. For example, `https://EXAMPLE.com/helloHI` would be treated as `https://example.com/helloHI`.
5. Perform any additional instructions to complete the form.
6. Review your entries.
7. Select **Purge**.

Note

For information on how to use single-file purge to purge assets cached by a Workers fetch, refer to [Single file purge assets cached by a Worker](https://developers.cloudflare.com/workers/reference/how-the-cache-works/#single-file-purge-assets-cached-by-a-worker).

For information on how to purge assets cached by [Cache API](https://developers.cloudflare.com/workers/runtime-apis/cache/) operations, refer to [Purge assets stored with the Cache API](https://developers.cloudflare.com/workers/reference/how-the-cache-works/#purge-assets-stored-with-the-cache-api).

Warning

If you have a [Transform Rule](https://developers.cloudflare.com/rules/transform/) in place that is modifying part of a URL path, you must use the non-transform (end user) URL when performing single file purge so that purge can take effect.

## Resulting cache status

Purging by single-file deletes the resource, resulting in the `CF-Cache-Status` header being set to [MISS](https://developers.cloudflare.com/cache/concepts/cache-responses/#miss) for subsequent requests.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/purge-cache/","name":"Purge cache"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/purge-cache/purge-by-single-file/","name":"​Purge by single-file"}}]}
```

---

---
title: Purge cache by cache-tags
description: Purge cached resources by cache tag headers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Purge cache by cache-tags

Cache-tag purging makes multi-file purging easier because you can instantly bulk purge by adding cache-tags to your assets, such as webpages, image files, and more.

## General workflow for cache-tags

1. Add tags to the `Cache-Tag` HTTP response header from your origin web server for your web content, such as pages, static assets, etc.
2. [Ensure your web traffic is proxied](https://developers.cloudflare.com/dns/proxy-status/) through Cloudflare.
3. Cloudflare associates the tags in the `Cache-Tag` HTTP header with the content being cached.
4. Use specific cache-tags to instantly purge your Cloudflare CDN cache of all content containing that cache-tag from your dashboard or [using our API](https://developers.cloudflare.com/api/resources/cache/methods/purge/).
5. Cloudflare forces a [cache MISS](https://developers.cloudflare.com/cache/concepts/cache-responses/#miss) on content with the purged cache-tag.

Warning

Be careful when purging. A cache MISS can cause execution delays by requiring a fetch from your origin server.

## Add Cache-Tag HTTP response headers

You add cache-tags to your web content in `Cache-Tag` HTTP response headers to allow the client and server to pass additional information in requests or responses. HTTP headers consist of a specific case-insensitive name followed by a colon `:` and the valid value, for example, `Cache-Tag:tag1,tag2,tag3`. Use commas to separate the tags when you want to use multiple cache-tags.

When your content reaches our edge network, Cloudflare:

* Removes the `Cache-Tag` HTTP header before sending the response to your website visitor or passing the response to a [Worker](https://developers.cloudflare.com/workers/). Your end users or Worker never see `Cache-Tag` HTTP headers on your Cloudflare-enabled website.
* Removes whitespaces from the header and any before and after cache-tag names: `tag1`, `tag2` and `tag1,tag2` are considered the same.
* Removes all repeated and trailing commas before applying cache-tags: `tag1,,,tag2` and `tag1,tag2` are considered the same.

## A few things to remember

* A single HTTP response can have more than one `Cache-Tag` HTTP header field.
* The minimum length of a cache-tag is one byte.
* Individual tags do not have a maximum length, but the aggregate `Cache-Tag` HTTP header cannot exceed 16 KB after the header field name, which is approximately 1,000 unique tags. Length includes whitespace and commas but does not include the header field name.
* For cache purges, the maximum length of a cache-tag in an API call is 1,024 characters.
* The `Cache-Tag` HTTP header must only contain printable ASCII encoded characters.
* Spaces are not allowed in cache-tags.
* Case is not sensitive. For example, `Tag1` and `tag1` are considered the same.

## Purge using cache-tags

1. In the Cloudflare dashboard, go to the **Configuration** page.  
[ Go to **Configuration** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/configuration)
2. Under **Purge Cache**, select **Custom Purge**. The **Custom Purge** window appears.
3. Under **Purge by**, select **Tag**.
4. In the text box, enter your tags to use to purge the cached resources. To purge multiple cache-tagged resources, separate each tag with a comma or have one tag per line.
5. Select **Purge**.

For information on rate limits, refer to the [Availability and limits](https://developers.cloudflare.com/cache/how-to/purge-cache/#availability-and-limits) section.

## Resulting cache status

Purging by tag deletes the resource, resulting in the `CF-Cache-Status` header being set to [MISS](https://developers.cloudflare.com/cache/concepts/cache-responses/#miss) for subsequent requests.

If [Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) is used, purging by tag may return `EXPIRED`, as the lower tier tries to revalidate with the upper tier to reduce load on the latter. Depending on whether the upper tier has the resource or not, and whether the end user is reaching the lower tier or the upper tier, `EXPIRED` or `MISS` are returned.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/purge-cache/","name":"Purge cache"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/purge-cache/purge-by-tags/","name":"Purge cache by cache-tags"}}]}
```

---

---
title: Purge cache key resources
description: Purge cached resources by custom cache key.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Purge cache key resources

Instantly purge resources that use Cache Keys via the [Cloudflare API](https://developers.cloudflare.com/api/resources/cache/methods/purge/). If you use [Cloudflare's Purge by URL](https://developers.cloudflare.com/api/resources/cache/methods/purge/#purge-cached-content-by-url), include the headers and query strings that are in your custom Cache Key.

Currently, it is not possible to purge a URL stored through Cache API that uses a custom cache key set by a Worker. Instead, use a [custom key created by Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#cache-key). Alternatively, purge your assets using purge everything, purge by tag, purge by host or purge by prefix.

To instantly purge by `device_type`, `geo`, or `lang` use `CF-Device-Type`, `CF-IPCountry` or `accept-language`, respectively. [Purge by Tag / Host](https://developers.cloudflare.com/api/resources/cache/methods/purge/#purge-cached-content-by-tag-host-or-prefix) and [Purge Everything](https://developers.cloudflare.com/api/resources/cache/methods/purge/#purge-all-cached-content) are not impacted by the use of custom Cache Keys.

## Purge by device type

For a Cache Key based on device type, purge the asset by passing the `CF-Device-Type` header with the API purge request (valid headers include mobile, desktop, and tablet).

Refer to the example API request below to instantly purge all mobile assets on the root webpage.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Cache Purge`

Purge Cached Content

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "files": [

        {

            "url": "http://my.website.com/",

            "headers": {

                "CF-Device-Type": "mobile"

            }

        }

    ]

  }'


```

## Purge by geo

Instantly purge resources for a location-based Cache Key by specifying the two-letter country code. Spain is used in the example below.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Cache Purge`

Purge Cached Content

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "files": [

        {

            "url": "http://my.website.com/",

            "headers": {

                "CF-IPCountry": "ES"

            }

        }

    ]

  }'


```

## Purge by language

For a Cache Key based on language, purge the asset by passing the `accept-language` header. Refer to the example API request below to instantly purge all assets in Chinese (PRC).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Cache Purge`

Purge Cached Content

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "files": [

        {

            "url": "http://my.website.com/",

            "headers": {

                "accept-language": "zh-CN"

            }

        }

    ]

  }'


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/purge-cache/","name":"Purge cache"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/purge-cache/purge-cache-key/","name":"Purge cache key resources"}}]}
```

---

---
title: ​Purge everything
description: Purge all cached content for your entire zone.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# ​Purge everything

To maintain optimal site performance, Cloudflare strongly recommends using single-file (by URL) purging instead of a complete cache purge.

Purging everything instantly clears all resources from your CDN cache in all Cloudflare data centers. Each new request for a purged resource returns to your origin server to validate the resource. If Cloudflare cannot validate the resource, Cloudflare fetches the latest version from the origin server and replaces the cached version. When a site with heavy traffic contains a lot of assets, requests to your origin server can increase substantially and result in slow site performance.

1. In the Cloudflare dashboard, go to the **Configuration** page.  
[ Go to **Configuration** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/configuration)
2. Under **Purge Cache**, select **Purge Everything**. A warning window appears.
3. If you agree, select **Purge Everything**.

Note

When purging everything for a non-production cache environment, all files for that specific cache environment will be purged. However, when purging everything for the production environment, all files will be purged across all environments.

For information on rate limits, refer to the [Availability and limits](https://developers.cloudflare.com/cache/how-to/purge-cache/#availability-and-limits) section.

## Resulting cache status

Purge Everything invalidates the resource, resulting in the `CF-Cache-Status` header indicating [EXPIRED](https://developers.cloudflare.com/cache/concepts/cache-responses/#expired) for subsequent requests.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/purge-cache/","name":"Purge cache"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/purge-cache/purge-everything/","name":"​Purge everything"}}]}
```

---

---
title: P​urge varied images
description: Purge cached image variants created by Vary for Images.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# P​urge varied images

Purging varied images instantly purges all content variants for that URL. This behavior occurs so that if an image changes, you can easily update the cache with a single purge request instead of trying to determine the potential number of out-of-date variants. The behavior is true regardless of [purge type](https://developers.cloudflare.com/cache/how-to/purge-cache/) used, such as [single file](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-single-file/), [tag](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-tags/), or [hostname](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-hostname/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/purge-cache/","name":"Purge cache"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/purge-cache/purge-varied-images/","name":"P​urge varied images"}}]}
```

---

---
title: Purge zone versions via API
description: Purge cache for specific zone versions using the API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Purge zone versions via API

To purge zone versions via the Cloudflare API, follow these steps:

## Step 1: Retrieve the environment ID

First, retrieve your zone's environment ID by sending a request to the following API endpoint:

Terminal window

```

https://api.cloudflare.com/client/v4/zones/<zone_id>/environments


```

This API call will return a JSON response similar to the example below:

```

{

  "result": {

    "environments": [

      {

        "name": "Production",

        "ref": "12abcd3e45f678940a573f51834a54",

        "version": 0,

        "expression": "(cf.zone.name eq \"example.com\")",

        "locked_on_deployment": false,

        "position": {

          "before": "5d41402abc4b2a76b9719d911017c"

        }

      },

      {

        "name": "Staging",

        "ref": "5d41402abc4b2a76b9719d911017c",

        "version": 0,

        "expression": "((cf.edge.server_ip in {1.2.3.4 5.6.7.8})) and (cf.zone.name eq \"example.com\")",

        "locked_on_deployment": false,

        "position": {

          "before": "49f0bad299687c62334182178bfd",

          "after": "12abcd3e45f678940a573f51834a54"

        }

      },

      {

        "name": "Development",

        "ref": "49f0bad299687c62334182178bfd",

        "version": 0,

        "expression": "((any(http.request.cookies[\"development\"][*] eq \"true\"))) and (cf.zone.name eq \"example.com\")",

        "locked_on_deployment": false,

        "position": {

          "after": "5d41402abc4b2a76b9719d911017c"

        }

      }

    ]

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

In this particular example, we have three environments: Production, Staging, and Development. You can find the environment ID in the `ref` field.

## Step 2: Purge cache per environment

To purge the Production environment, use the general cache purge endpoint:

Terminal window

```

https://api.cloudflare.com/client/v4/zones/<zone_id>/purge_cache/


```

To purge non-production environments, you must use a new `purge_cache` endpoint and specify the environment you would like to purge.

To purge the Staging environment from the example above, send a request to the following endpoint:

Terminal window

```

https://api.cloudflare.com/client/v4/zones/<zone_id>/environments/5d41402abc4b2a76b9719d911017c/purge_cache/


```

To purge the Development environment from the example above, send a request to the following endpoint:

Terminal window

```

https://api.cloudflare.com/client/v4/zones/<zone_id>/environments/49f0bad299687c62334182178bfd/purge_cache/


```

Note

When purging everything for a non-production cache environment, all files for that specific cache environment will be purged. However, when purging everything for the production environment, all files will be purged across all environments.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/purge-cache/","name":"Purge cache"}},{"@type":"ListItem","position":5,"item":{"@id":"/cache/how-to/purge-cache/purge-zone-versions/","name":"Purge zone versions via API"}}]}
```

---

---
title: Caching levels
description: Set caching levels to control query string behavior.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Caching levels

Caching levels determine how much of your website’s static content Cloudflare should cache. Cloudflare’s CDN caches static content according to the levels below.

* **No Query String**: Delivers resources from cache when there is no query string. Example URL: `example.com/pic.jpg`
* **Ignore Query String**: Delivers the same resource to everyone independent of the query string. Example URL: `example.com/pic.jpg?ignore=this-query-string`
* **Standard (Default)**: Delivers a different resource each time the query string changes. Example URL: `example.com/pic.jpg?with=query`

You can adjust the caching level from the dashboard under **Caching** \> **Configuration** \> **Caching level**.

Note

Ignore Query String only disregards the query string for static file extensions. For example, Cloudflare serves the `style.css` resource to requests for either `style.css?this` or `style.css?that`.

## API Caching level values

If you are using the API to change the cache level, the values will differ from those shown in the dashboard. Refer to the table below to see how the API values map to the values shown in the dashboard.

| Dashboard           | API        |
| ------------------- | ---------- |
| No Query String     | Basic      |
| Ignore Query String | Simplified |
| Standard (Default)  | Aggressive |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/set-caching-levels/","name":"Caching levels"}}]}
```

---

---
title: Tiered Cache
description: Reduce origin requests with tiered cache topology.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Tiered Cache

Tiered Cache uses the size of the Cloudflare network to reduce requests to customer origins by dramatically increasing cache hit ratios. With data centers around the world, Cloudflare caches content very close to end users. However, if a piece of content is not in cache, the Cloudflare edge data centers must contact the origin server to receive the cacheable content.

Tiered Cache works by dividing Cloudflare’s data centers into a hierarchy of lower-tiers and upper-tiers. If content is not cached in lower-tier data centers (generally the ones closest to a visitor), the lower-tier must ask an upper-tier to see if it has the content. If the upper-tier does not have the content, only the upper-tier can ask the origin for content. This practice improves bandwidth efficiency by limiting the number of data centers that can ask the origin for content, which reduces origin load and makes websites more cost-effective to operate.

Additionally, Tiered Cache concentrates connections to origin servers so they come from a small number of data centers rather than the full set of network locations. This results in fewer open connections using server resources.

To enable Tiered Cache, refer to [Enable Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/#enable-tiered-cache).

## Tiered Cache Topology

Cloudflare allows you to select your cache topology so that you have control over how your origin connects to Cloudflare’s data centers. This will help ensure higher cache hit ratios, fewer origin connections, and a reduction of Internet latency. Below you can find details about the options we have available.

### Smart Tiered Cache

Smart Shield

This functionality is now offered as part of Cloudflare's origin server safeguard, Smart Shield. [Learn more](https://developers.cloudflare.com/smart-shield/).

Smart Tiered Cache dynamically selects the single closest upper tier for each of your website’s origins with no configuration required, using our in-house performance and routing data. Cloudflare collects latency data for each request to an origin, and uses the latency data to determine how well any upper-tier data center is connected with an origin. As a result, Cloudflare can select the data center with the lowest latency to be the upper-tier for an origin.

#### Public cloud origins

Origins hosted on public cloud providers (AWS, GCP, Azure, or Oracle Cloud) often use [anycast ↗](https://www.cloudflare.com/en-gb/learning/cdn/glossary/anycast-network/) or regional unicast networking, which prevents Smart Tiered Cache from determining the origin location through latency probing alone. To solve this, you can set a **cloud region hint** that tells Smart Tiered Cache which cloud provider and region your origin is in. Smart Tiered Cache then selects a primary upper-tier data center close to that cloud region, plus a fallback in a different location for resilience. To set up a cloud region hint, refer to [Set a cloud region hint](https://developers.cloudflare.com/cache/how-to/tiered-cache/#set-a-cloud-region-hint).

#### Load Balancing interaction

While Smart Tiered Cache selects one Upper Tier per origin, when using Load Balancing, Smart Tiered Cache will select the single best Upper Tier for the entire [Load Balancing Pool](https://developers.cloudflare.com/load-balancing/understand-basics/load-balancing-components/#pools).

#### Caveats

You need to be careful when updating your origin IPs/DNS records while Smart Tiered Cache is enabled. Depending on the changes made, it may cause the existing assigned upper tiers to change, resulting in an increased `MISS` rate as cache is refilled in the new upper tiers. If the origin is switched to a network behind anycast, it will significantly reduce the effectiveness of Smart Tiered Cache unless you set a [cloud region hint](https://developers.cloudflare.com/cache/how-to/tiered-cache/#set-a-cloud-region-hint).

### Generic Global Tiered Cache

Generic Global topology allows for all of Cloudflare’s global data centers to serve as a network of upper-tiers. This topology may help reduce the long tail latencies for far-away visitors.

### Regional Tiered Cache

Smart Shield

This functionality is now offered as part of Cloudflare's origin server safeguard, Smart Shield. [Learn more](https://developers.cloudflare.com/smart-shield/).

Regional Tiered Cache provides an additional layer of caching for customers who have a global traffic footprint and want to serve content faster by avoiding network latency when there is a cache `MISS` in a lower-tier, resulting in an upper-tier fetch in a data center located far away.

Regional Tiered Cache instructs Cloudflare to check a regional hub data center near the lower tier before going to the upper tier that may be outside of the region.

This can help improve performance for **Smart** and **Custom Tiered Cache** topologies with upper-tiers in one or two regions. Regional Tiered Cache is not beneficial for customers with many upper tiers in many regions like Generic Global Tiered Cache.

### Custom Tiered Cache

Custom Tiered cache allows Enterprise customers to work with their account team to set a custom topology that fits your specific needs, for instance you have close upper tiers or you have a unique traffic pattern. If you want a custom topology, please engage your account team.

## Availability

| Free                    | Pro | Business | Enterprise |     |
| ----------------------- | --- | -------- | ---------- | --- |
| Tiered Cache            | Yes | Yes      | Yes        | Yes |
| Smart Topology          | Yes | Yes      | Yes        | Yes |
| Generic Global Topology | No  | No       | No         | Yes |
| Regional Tiered Cache   | No  | No       | No         | Yes |
| Custom Topology         | No  | No       | No         | Yes |

## Bandwidth Alliance

Enterprise customers can override Bandwidth Alliance configuration with Tiered Cache. For all other users, the Bandwidth Alliance takes precedence. Tiered Cache is still a valuable option to enable because the Bandwidth Alliance may not always be an available option, and in those instances, the Tiered Cache configuration will be used.

## Enable Tiered Cache

You can enable Tiered Cache in the dashboard or via API.

### Enable Tiered Cache in the dashboard

1. In the Cloudflare dashboard, go to the **Tiered Cache** page.  
[ Go to **Tiered Cache** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/tiered-cache)
2. From **Tiered Cache**, toggle the button to **enabled**.
3. In **Tiered Cache Topology**, you can control how your origin connects to Cloudflare’s data centers. You can select:  
   * **Upper Tier Cache** \- You have the option to choose between Smart or Generic Global Tiered Cache Topology.  
   * **Middle Tier Cache** \- If you have selected Smart or Custom Tiered Cache Topology, you can now enable Regional Tiered Cache.  
   * **Custom Tiered Cache** \- Allows you to work with Cloudflare’s support team to set a custom topology that fits your specific needs.  
   * **Disable Tiered Cache**.
![Tiered Cache Topology dashboard](https://developers.cloudflare.com/_astro/tiered_cache_topology.sy3gfwwc_Z1XYoHF.webp) 

### Enable Tiered Cache via API

To enable Tiered Cache via API use the following cURL example:

Patch Tiered Caching setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/argo/tiered_caching" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": "on"

  }'


```

You can also configure Tiered Cache Topology via API, for instance:

Enable Smart Tiered Cache

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`
* `Zone Write`

Patch Smart Tiered Cache setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/cache/tiered_cache_smart_topology_enable" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": "on"

  }'


```

Enable Regional Tiered Cache

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`
* `Zone Write`

Change Regional Tiered Cache setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/cache/regional_tiered_cache" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": "on"

  }'


```

For more API examples and configuration options for Tiered Cache, refer to the [API documentation](https://developers.cloudflare.com/api/resources/argo/subresources/tiered%5Fcaching/methods/get/).

### Set a cloud region hint

If your origin is hosted on a public cloud provider, set a cloud region hint so Smart Tiered Cache can select the optimal upper tier for your cloud region. For background on why this is needed, refer to [Public cloud origins](https://developers.cloudflare.com/cache/how-to/tiered-cache/#smart-tiered-cache).

Cloud region hints are available on all plan types (Free, Pro, Business, and Enterprise) at no additional cost. Supported providers: AWS, GCP, Azure, and Oracle Cloud.

#### Set a cloud region hint in the dashboard

1. Go to **Caching** \> **Tiered Cache** \> **Origin Configuration**.  
[ Go to **Tiered Cache** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/tiered-cache)
2. Find your origin IP or hostname and select **Set Region Hint**.
3. Select your cloud provider and region (for example, `aws:us-east-1` or `gcp:europe-west1`).

#### List supported cloud regions via API

To see all available cloud providers and regions, use the supported regions endpoint:

List supported cloud vendors and regions

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/cache/origin_cloud_regions/supported_regions" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

#### Set a cloud region hint via API

Create or update an origin cloud region mapping

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/cache/origin_cloud_regions" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "ip": "203.0.113.1",

    "vendor": "aws",

    "region": "us-east-1"

  }'


```

Note

Custom Tiered Cache settings take precedence over cloud region hint mappings. If you have a custom topology configured, the cloud region hint will not override it.

Note

To confirm that Tiered Cache is working, make sure you have the value of [CacheTieredFill](https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/zone/http%5Frequests/#cachetieredfill) in your http\_requests logs, this will indicate if Tiered Cache was used to serve the request.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/how-to/","name":"Cache configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/how-to/tiered-cache/","name":"Tiered Cache"}}]}
```

---

---
title: Cache Analytics
description: View cache hit rates and bandwidth savings in Cache Analytics.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache Analytics

Cache Analytics shows how much of your site's traffic is served from Cloudflare's cache versus your origin server. When content is served from cache, visitors get faster page loads and your origin web server handles less traffic. Use Cache Analytics to identify resources that are [missing from cache](https://developers.cloudflare.com/cache/concepts/cache-responses/#miss), [expired](https://developers.cloudflare.com/cache/concepts/cache-responses/#expired) (cached copy is outdated), or [ineligible for caching](https://developers.cloudflare.com/cache/concepts/cache-responses/#noneunknown) (not eligible for caching). You can filter by hostname, review the top URLs that miss cache, and query up to three days of data.

## Availability

| Free             | Pro | Business | Enterprise |         |
| ---------------- | --- | -------- | ---------- | ------- |
| Availability     | No  | Yes      | Yes        | Yes     |
| Retention period | N/A | 7 days   | 30 days    | 30 days |

## Access Cache Analytics

In the Cloudflare dashboard, go to the **Caching** page.

[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/caching) 

## Requests vs Data Transfer

You can decide whether to focus on **Requests** or **Data Transfer**:

* **Requests** (default view) helps assess performance. Each cache [MISS](https://developers.cloudflare.com/cache/concepts/cache-responses/#miss) means the request must go to your origin server instead of being served from Cloudflare's cache, which adds latency.
* **Data Transfer** is useful for cost analysis, since most hosting providers charge for data sent from their servers (egress bandwidth).

You can switch between these views while keeping other analytics filters applied.

For best practices related to Cache Analytics, refer to [Cache performance](https://developers.cloudflare.com/cache/performance-review/cache-performance/).

## Add filters

Create filters to narrow the data to specific traffic segments. Example filters include **Cache status**, **Host**, **Path**, or **Content type**.

To add filters, under **Cache Performance**, select **Add filter**. Select **Apply** when you are done.

## Review cache status

The **Requests summary** graph shows how your traffic changes over time, such as in response to a high-traffic event or a recent configuration change. The Requests summary is based on a sample of requests, not the full dataset. Totals are extrapolated from the sample to represent overall traffic. For more information on how sampling works, refer to [Understanding sampling in Cloudflare Analytics](https://developers.cloudflare.com/analytics/sampling/).

**Served by Cloudflare** indicates content served by Cloudflare that did not require contacting your origin web server. **Served by Origin** indicates traffic served from the origin web server.

Revalidated requests — where Cloudflare checks with your origin to confirm cached content is still current — are counted differently depending on the view. In the **Data Transfer** view, revalidated requests count as **Served by Cloudflare** because the response body is served from cache, not re-downloaded from the origin. In the **Requests** view, revalidated requests count as **Served by Origin** because Cloudflare still contacts the origin server to verify the content.

**Cache status** graphs break down why traffic is served from Cloudflare versus the origin web server, organized by content type.

For a breakdown of cache statuses and their descriptions, refer to [Cloudflare cache responses](https://developers.cloudflare.com/cache/concepts/cache-responses/).

## Review requests by source

Cache Analytics shows the most frequent values (top N) for several request attributes. Apply filters before reviewing these metrics to focus on specific traffic. For example, filtering to only view traffic with an Expired or Revalidated cache status shows which URLs were primarily responsible for those statuses.

### Empty content types

Finding an **empty** content type in your analytics is common. Responses to redirect status codes (`301`/`302`) typically do not include content, so they have no content type. Similarly, many HTTP error responses, such as `403`, do not return `text/html` and are also reported as empty.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/performance-review/","name":"Performance review"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/performance-review/cache-analytics/","name":"Cache Analytics"}}]}
```

---

---
title: Cache performance
description: Measure and improve cache performance for your site.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache performance

## Optimize cache ratios

Your cache ratio measures how often Cloudflare serves content from cache instead of contacting your origin server. A higher ratio means faster responses for visitors and less traffic to your origin.

Depending on the [cache status](https://developers.cloudflare.com/cache/concepts/cache-responses/) you receive, you can make modifications to improve your cache ratio.

* **Dynamic**: The resource was not eligible for caching. This is the default response for many file types including HTML. To cache additional content, refer to [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/).
* **Revalidated**: The resource was in cache but Cloudflare confirmed with your origin that it was still current before serving it. To address an atypical quantity of revalidated content, consider [increasing your Edge Cache TTLs](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#edge-ttl) (how long Cloudflare considers cached content fresh before checking your origin).
* **Expired**: The cached resource's TTL elapsed before it was requested again. Consider [extending Edge Cache TTLs](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#edge-ttl) for these resources via a Cache Rule, or configure your origin to return [revalidation headers](https://developers.cloudflare.com/cache/concepts/cache-control/) (`Last-Modified` or `ETag`) so Cloudflare can confirm content is still current without downloading it again.
* **Miss**: The resource was not found in cache and was served from your origin. Although tricky to optimize, there are a few potential remedies:  
   * [Enable Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/#enable-tiered-cache) to check an upper-tier Cloudflare data center before contacting your origin server.  
   * [Create a custom cache key](https://developers.cloudflare.com/cache/how-to/cache-rules/examples/custom-cache-key/) so that multiple URLs match the same cached resource, for example by ignoring the query string.

## Troubleshoot cache performance with example reports

Use [Cache Analytics](https://developers.cloudflare.com/cache/performance-review/cache-analytics/) to identify cache performance issues. The following examples show how to filter for common problems and resolve them.

* Not caching HTML.  
   * Identify the issue: Select **Add filter** and select **Cache status equals Dynamic**.  
   * Resolution: Set a Cloudflare Cache Rule to [cache dynamic content](https://developers.cloudflare.com/cache/how-to/cache-rules/examples/cache-everything/).

Warning

This option caches all HTML regardless of the presence of dynamic content (content that changes per visitor, such as time of visit, location, or device). If you use this approach to cache pages containing dynamic content, visitors may receive information not intended for them. To avoid caching dynamic content, add a condition to the rule's matching criteria to exclude it. Some examples include:

* Checking for the presence of a cookie.
* Excluding requests that match known dynamic content file paths.
* Excluding requests with dynamic content extensions (or no extension).

* Short cache expiration TTL.  
   * Identify the issue: Select **Add filter** and select **Cache status equals Revalidated**.  
   * Resolution: [Increase Cloudflare's Edge Cache TTL via a Cache Rule](https://developers.cloudflare.com/cache/how-to/cache-rules/examples/edge-ttl/).
* Need to enable Tiered Cache or custom cache key.  
   * Identify the issue: Select **Add filter** and select **Cache status equals Miss**.  
   * Resolution: [Enable Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/#enable-tiered-cache) or [create a custom cache key](https://developers.cloudflare.com/cache/how-to/cache-rules/examples/custom-cache-key/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/performance-review/","name":"Performance review"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/performance-review/cache-performance/","name":"Cache performance"}}]}
```

---

---
title: Content Delivery Network (CDN) Reference Architecture
description: This reference architecture discusses the traditional challenges customers face with web applications, how the Cloudflare CDN resolves these challenges, and CDN architecture and design.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Content Delivery Network (CDN) Reference Architecture

**Last reviewed:**  over 3 years ago 

## Introduction

Every day, users of the Internet enjoy the benefits of performance and reliability provided by [content delivery networks ↗](https://www.cloudflare.com/learning/cdn/what-is-a-cdn/) (CDNs). CDNs have become a must-have to combat latency and a requirement for any major company delivering content to users on the Internet. While providing performance and reliability for customers, CDNs also enable companies to further secure their applications and cut costs. This document discusses the traditional challenges customers face with web applications, how the Cloudflare CDN resolves these challenges, and CDN architecture and design.

### Who is this document for and what will you learn?

This reference architecture is designed for IT or network professionals with some responsibility over or familiarity with their organization's existing infrastructure. It is useful to have some experience with technologies and concepts important to content delivery, including caching, DNS and firewalls.

To build a stronger baseline understanding of Cloudflare, we recommend the following resources:

* What is Cloudflare? | [Website ↗](https://www.cloudflare.com/what-is-cloudflare/) (5 minute read) or [video ↗](https://youtu.be/XHvmX3FhTwU?feature=shared) (2 minutes)
* What is a CDN? | [Website ↗](https://www.cloudflare.com/learning/cdn/what-is-a-cdn/) (5 minute read)
* Analyst Report: [Cloudflare named Leader in 2024 GigaOm Radar for Content Delivery Networks ↗](https://www.cloudflare.com/lp/gigaom-radar-cdn/) (20 minute read)

Those who read this reference architecture will learn:

* How Cloudflare CDN can significantly improve the delivery of content to your customers
* How anycast IP routing is important in ensuring reliable CDN performance
* The range of tiered caching options and how to choose the one for your needs

## Traditional challenges deploying web applications

Over the last several years, especially with the advent of the COVID-19 pandemic and the focus on remote work, there has been a significant growth in Internet traffic, further growing the need to efficiently manage network traffic, cut latency, and increase performance.

Companies running their applications in the cloud or on-premise are faced with the challenges of:

1. Implementing solutions to increase performance
2. As demand grows, scaling out their architecture to meet availability and redundancy concerns
3. Securing their environments and applications from growing Internet threats
4. Reining in growing costs related to doing all of the above

With companies serving customers across the globe, the above challenges require a significant undertaking. Traditionally, a website/application is deployed centrally and replicated to another region for availability, or the website/application is deployed across a handful of servers, sometimes across multiple data centers for resiliency.

The servers hosting the websites are called origin servers. When clients access a website, they make a request for resources from the server. Navigating to one website can generate hundreds of requests from the browser for HTML, CSS, images, videos, etc. With versions of HTTP prior to HTTP/2, each of these HTTP requests would also require a new TCP connection.

Enhancements in HTTP/2 and HTTP/3 allow for multiplexing multiple requests to the same server over a single TCP connection, thus saving server resources. However, compute and network resources are still consumed as servers respond to these requests. As more clients access the website, the following can result:

* The origin server starts to become overloaded with requests, impacting availability; companies start looking at scaling out to handle the additional load
* As each request has to make its way to the origin server, performance and user experience is impacted due to latency
* The latency for end users becomes proportional to the distance between the client and origin server, thus resulting in varying experiences based on client location. This is especially true for specific countries that may experience latency due to traffic from or to that country, like China.
* As origin servers respond to the increasing requests, bandwidth, egress, and compute costs increase drastically
* Even as customers scale out to handle the increased demand in traffic, they are left exposed to both infrastructure-level and application-level distributed denial-of-service (DDoS) attacks

In Figure 1 below, there is no CDN present and there is an origin server sitting in the US. As clients access the website, the first step is DNS resolution, typically done by the user’s ISP. The next step is the HTTP request sent directly to the origin server. The user experience will vary depending on their location. For example, you can see the latency is much lower for users in the US, where the origin server is located. For users outside the US, the latency increases, thus resulting in a higher round-trip time (RTT).

As more clients make requests to the origin server, the load on the network and server increases, resulting in higher latency and higher costs for resource and bandwidth use.

From a security perspective, the origin server is also vulnerable to DDoS attacks at both the infrastructure and application layer. A DDoS attack could be initiated from a botnet sending millions of requests to the origin server, consuming resources and preventing it from serving legitimate clients.

Further, in terms of resiliency, if the origin server temporarily goes offline, all content is inaccessible to users.

![Figure 1: Diagram of HTTP web requests between DNS and origin server without a CDN.](https://developers.cloudflare.com/_astro/ref-arch-cdn-figure1.BH2E9Wnc_2oxdBw.svg "Figure 1: HTTP Request with no CDN")

Figure 1: HTTP Request with no CDN

## How a CDN tackles web application challenges

A CDN helps address the challenges customers face around latency, performance, availability, redundancy, security, and costs. A CDN's core goal is to decrease latency and increase performance for websites and applications by caching content as close as possible to end users or those accessing the content.

CDNs decrease latency and increase performance by having many data center locations across the globe that cache the content from the origin. The goal is to have content cached as close as possible to users, so content is cached at the edge of the CDN provider's network.

### Impacts

* **Improved website load time**: Instead of every client making a request to the origin server, which could be located a considerable distance away, the request is routed to a local server that responds with cached content, thus decreasing latency and increasing overall performance. Regardless of where the origin server and clients are located, performance will be more consistent for all users, as the CDN will serve locally cached content when possible.
* **Increased content availability and redundancy:** Because every client request no longer needs to be sent to the origin server, CDNs provide not only performance benefits, but also availability and redundancy. Requests are load balanced over local servers with cached content; these servers respond to local requests, significantly decreasing overall load on the origin server. The origin server only is contacted when needed (when content is not cached or for dynamic non-cacheable content).
* **Improved website security:** A CDN acts as a reverse proxy and sits in front of origin servers. Thus it can provide enhanced security such as DDoS mitigation, improvements to security certificates, and other optimizations.
* **Reduced bandwidth costs:** Because CDNs use cached content to respond to requests, the number of requests sent to the origin server is reduced, thus also reducing associated bandwidth costs.

### Routing requests to CDN nodes

An important difference in some CDN implementations is how they route traffic to the respective local CDN nodes. Routing requests to CDN nodes can be done via two different methods:

**DNS unicast routing**

In this method, recursive DNS queries redirect requests to CDN nodes; the client’s DNS resolver forwards requests to the CDN’s authoritative nameserver. CDNs based on DNS unicast routing are not ideal in that clients may be geographically dispersed from the DNS resolver. Decisions on closest-proximity CDN nodes are based on the client's DNS server instead of client’s IP address. Also, if any changes are needed for the DNS response, there is a dependency on DNS time to live (TTL) expiration.

Further, since DNS routing uses unicast addresses, traffic is routed directly to a specific node, creating possible concerns when there are traffic spikes, as in a DDoS attack.

Another challenge with DNS-based CDNs is that DNS is not very graceful upon failover. Typically a new session or application must be started for the DNS resolver with a different IP address to take over.

**Anycast routing**

The Cloudflare CDN, which is discussed in more detail in the next section, uses anycast routing. Anycast allows for nodes on a network to have the same IP address. The same IP address is announced from multiple nodes in different locations, and client redirection is handled via the Internet’s routing protocol, BGP.

Using an anycast-based CDN has several advantages:

* Incoming traffic is routed to the nearest data center with the capacity to process the requests efficiently.
* Availability and redundancy is inherently provided. Since multiple nodes have the same IP address, if one node were to fail, requests are simply routed to another node in close proximity.
* Because anycast distributes traffic across multiple data centers, it increases the overall surface area, thus preventing any one location from becoming overwhelmed with requests. For this reason, anycast networks are very resilient to DDoS attacks.

## Introducing the Cloudflare CDN

Cloudflare provides a Software as a Service (SaaS) model for CDN. With Cloudflare’s SaaS model, customers benefit from the Cloudflare CDN without having to manage or maintain any infrastructure or software.

The benefits of the Cloudflare CDN can be attributed to the below two points, discussed in more detail in this section.

1. CDNs inherently increase performance by caching content on servers close to the user
2. The unique Cloudflare architecture and integrated ecosystem

Figure 2 shows a simplified view of the Cloudflare CDN. Clients are receiving their response back from a server on Cloudflare’s global anycast network closest to where the clients are located, thus drastically reducing the latency and RTT. The diagram depicts a consistent end-user experience regardless of the physical location of the clients and origin.

![Figure 2 is a diagram representing the traffic between a client and a server on Cloudflare's global anycast network at different client locations.](https://developers.cloudflare.com/_astro/ref-arch-cdn-figure2.DP9jXMC9_Z135xXW.svg "Figure 2: HTTP request to Cloudflare CDN with anycast")

Figure 2: HTTP request to Cloudflare CDN with anycast

## Cloudflare CDN architecture and design

Figure 3 is a view of the Cloudflare CDN on the global anycast network. In addition to using anycast for network performance and resiliency, the Cloudflare CDN leverages Tiered Cache to deliver optimized results while saving costs for customers. Customers can also [enable Argo Smart Routing](https://developers.cloudflare.com/argo-smart-routing/get-started/) to find the fastest network path to route requests to the origin server. These capabilities are discussed in detail in the remainder of this document.

![Figure 3: Diagram representing requests coming from an end user, protected by Cloudflare products including WAF and DDoS protection, and traveling through the anycast Network to reach the origin server using Smart Tiered Cache.](https://developers.cloudflare.com/_astro/ref-arch-cdn-figure3.CcIfEHZq_STCJW.svg "Figure 3: Cloudflare CDN with Tiered Cache on global anycast network")

Figure 3: Cloudflare CDN with Tiered Cache on global anycast network

In the above diagram, there are a few important key points to understand about the Cloudflare CDN and the global anycast network it resides on:

* An important differentiator is that Cloudflare utilizes one global network and runs every service on every server in every Cloudflare data center, thus providing end users the closest proximity to Cloudflare’s services, with the highest scale, resiliency, and performance.
* Cloudflare is a reverse proxy, meaning it receives requests from clients and proxies the requests back to the customer’s origin servers. Thus, every request traverses through Cloudflare’s network before reaching the customer’s network. Since Cloudflare has hardened and protected its infrastructure at the edge (ingress), all customers are consequently also protected from infrastructure-level and volumetric DDoS attacks. Requests and traffic must go through the protected Cloudflare network before reaching the customer’s origin server.
* The Cloudflare CDN leverages the Cloudflare global anycast network. Thus the incoming request is routed to and answered by the node closest to the user.
* The inherent benefits of anycast are decreased latency, network resiliency, higher availability, and increased security due to larger surface area for absorbing both legitimate traffic loads and DDoS attacks. Cloudflare’s global anycast network spans [hundreds of cities worldwide ↗](https://www.cloudflare.com/network/), reaching 95% of the world’s Internet-connected population within 50 milliseconds while providing over 405 Tbps network capacity and DDoS protection capability.
* Edge nodes within the Cloudflare network cache content from the origin server and are able to respond to requests via a cached copy. Cloudflare also provides [DNS](https://developers.cloudflare.com/dns/), [DDoS protection](https://developers.cloudflare.com/ddos-protection/), [WAF](https://developers.cloudflare.com/waf/), and other performance, reliability, and security services using the same edge architecture.
* [Argo](https://developers.cloudflare.com/argo-smart-routing/) uses optimized routing and caching technology across the Cloudflare network to deliver responses to users more quickly, reliably, and securely. Argo includes Smart Routing and [Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/). Cloudflare leverages Argo to provide an enhanced CDN solution.

### Tiered Cache

Once a site is onboarded, standard caching is configured by default. With standard caching, each data center acts as a direct reverse proxy for the origin servers. A cache miss in any data center results in a request being sent to the origin server from the ingress data center.

Although standard caching works, it is not the most optimal design — cached content closer to the client may already exist in other Cloudflare data centers, and origin servers are sometimes unnecessarily overloaded as a result. Thus, it is best to enable Tiered Cache, which is included with every Cloudflare plan. With Tiered Cache, certain data centers are reverse proxies to the origin for other data centers, resulting in more cache hits and faster response times.

Tiered Cache leverages the scale of Cloudflare’s network to minimize requests to customer origins. When a request comes into a Cloudflare data center, if the requested content is not locally cached, other Cloudflare data centers are checked for the cached content.

Cloudflare data centers have shorter distances and faster paths between them than the connections between data centers and customer origin servers, optimizing the response to the client with a significant improvement in cache hit ratio. The Cloudflare CDN leverages Argo Smart Routing data to determine the best upper tier data centers to use for Tiered Cache. Argo Smart Routing can also be enabled as an add-on to provide the fastest paths between data centers and origin servers for cache misses and other types of dynamic traffic.

The Cloudflare CDN allows customers to configure tiered caching. Note that depending on the Cloudflare plan, different topologies are available for Tiered Cache. By default, tiered caching is disabled and can be enabled under the caching tab of the main menu. ​​

#### Tiered Cache topologies

The different cache topologies allow customers to control how Cloudflare interacts with origin servers to help ensure higher cache hit ratios, fewer origin connections, and reduced latency.

| **Smart Tiered Cache Topology (all plans)**                                                                                                                           | **Generic Global Tiered Topology (Enterprise only)**                                                                                              | **Custom Tiered Cache Topology (Enterprise only)**                                                                                                                         |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Recommended for most deployments. It is the default configuration once Tiered Cache is enabled.                                                                       | Recommended for those who have high traffic that is spread across the globe and desire the highest cache usage and best performance possible.     | Recommended for customers who have additional data on their user base and have specific geographic regions they would like to focus on.                                    |
| Ideal for customers who want to leverage CDN for performance but minimize requests to origin servers and bandwidth utilization between Cloudflare and origin servers. | Generic Global Tiered Topology balances between cache efficiency and latency. Instructs Cloudflare to use all Tier 1 data centers as upper tiers. | Custom Tiered Cache Topology allows customers to set a custom topology that fits specific needs (ex: upper tiers in specific geographic locations serving more customers). |
| Cloudflare will dynamically find the single best upper tier for an origin using Argo performance and routing data.                                                    | Engage your account team to build a custom topology.                                                                                              |                                                                                                                                                                            |

### Traffic flow: Tiered Cache, Smart Tiered Cache topology

In Figure 4, Tiered Caching is enabled with Smart Tiered Cache Topology. The diagram depicts two separate traffic flows, summarized below. The first traffic flow (Client 1) is a request from a client that comes into Data Center 1\. The second traffic flow (Client 2) is a subsequent request for the same resource into a different data center, Data Center 2.

![Figure 4: The same diagram as Figure 3 demonstrating requests between end users and origin server over the anycast Network, with bidirectional arrows indicating traffic flow enabled by Smart Tiered Cache.](https://developers.cloudflare.com/_astro/ref-arch-cdn-figure4.kIutXMs6_Z239rdF.svg "Figure 4: HTTP requests and traffic flow through Cloudflare CDN")

Figure 4: HTTP requests and traffic flow through Cloudflare CDN

| Request 1                                                                                                                                                                                                                                                                                                                                     | Request 2                                                                                                                                                            |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| First request received in Data Center 1 results in cache miss, as request had not been made previously by any client.                                                                                                                                                                                                                         | Second request by a different client received in Data Center 3 results in cache miss, as request had not been made previously by any client served by Data Center 3. |
| No cached content found, so Data Center 1 checks with its upper tier data center to request a copy of the content.                                                                                                                                                                                                                            | No cached content found, so Data Center 3 checks with the upper tier data center to request a copy of the content.                                                   |
| Upper tier data center also does not have content cached locally, so it makes a request to the origin server for content. Upon receiving the content, the upper tier data center caches it locally and relays the content to the requesting lower tier data center. The lower tier data center caches the content and responds to the client. | Cached content found at the upper tier data center. Data Center 3 retrieves and caches this content locally and responds to the client.                              |

In Figure 4, the top end user traffic flow displays the traffic flow when a client request is received by a data center closest to the client, Data Center 1\. Since there is nothing locally cached on the ingress data center and tiered caching is enabled, a request is sent to the upper tier data center to request a copy of the content to cache. Because the upper tier data center also does not have the content cached, it sends the request to the origin server, caches the received content upon response, and responds to the lower tier data center with the cached content. The lower tier data center caches the content and responds to the client.

Notice that when a new request for the same content is made to another data center (bottom end user traffic flow), Data Center 3, the content is not locally cached; however, the content is retrieved from the upper tier data center, where it was cached from the first request for the same content.

With the upper tier data center returning the cached content for the second request, the trip to the origin server is prevented, resulting in higher cache hit ratios, faster response times, saved bandwidth cost between the Cloudflare network and the origin server, and reduced load on the origin server responding to requests.

### Regional Tiered Cache

The main difference between Smart Tiered Cache and Global tiered cache is the number of upper tiers that can talk to the origin servers. With Smart Tiered Cache the closest upper tier to the origin is selected using Argo performance and routing data. This means that all requests that experience a cache `MISS` at a lower tier will funnel through this single upper tier and have a higher percentage chance of a cache `HIT` to avoid sending traffic to an origin server. However, the downside to this architecture is that the lower tier could be located across the globe from the upper tier. Even if the upper tier can fulfill the request from its cache, the distance between the upper tier and lower tier could still add latency to the response depending on the distance traveled. To summarize, Smart Tiered Cache ensures that all requests for cache flow through a single upper tier cache location which increases cache `HIT` percentages, and reduces requests to the origin server, however it can result in higher latencies fulfilling those requests since the upper tier could be located far away from the lower tier that originated the request.

With Generic Global Tiered Cache, Cloudflare uses its largest data centers around the globe as upper tier cache which means, in general, that the upper tier cache is much closer to the lower tier cache. This can greatly reduce latency when lower tiers need to pass requests to upper tiers. However, this ultimately will increase the amount of requests serviced by the origin as each upper tier cache will need to populate from the origin. To summarize, Generic Global Tiered cache can improve response times when cache is populated, but will also increase load on the origin servers.

Regional Tiered Cache combines the best of both of these strategies together by adding an additional layer of cache to the architecture. Using the Regional Tiered Cache option with Smart Tiered Caching means that while a single upper tier cache location exists closest to the origin, a Regional Tier layer has been added between the upper and lower tier that is geographically closer to the lower tier. Now, requests from lower tiers will now check a Regional Tier for cache before being sent to an upper tier. A single Regional Tier can accept requests from several lower tier caches and because of that, can greatly improve performance and latency for globally available applications.

Regional Tiered Caching is recommended for use with Smart Tiered Caching and Custom Tiered Caching. However, Regional Tiered Cache is not beneficial for customers with many upper tiers in many regions like Generic Global Tiered Cache.

#### Traffic flow: Tiered Cache, Smart Tiered Cache with Regional Tiered Cache

In Figure 5, Tiered Caching is enabled with Smart Tiered Cache Topology. The diagram depicts the topology of Smart Tiered Cache with Regional Tiered Cache enabled. Lower tier caches, when they experience a cache `MISS` will first send those requests to a more local, regional hub data center to see if the cache can handle the request. If not, the request will continue on to the upper tier and then origin server, if necessary.

![Figure 5: Diagram illustrating requests between an end user and origin server with lower, regional and upper tiered caching enabled.](https://developers.cloudflare.com/_astro/ref-arch-cdn-figure5.B3Tq_F2z_Z239rdF.svg "Figure 5: Cloudflare CDN with Tiered Cache and Regional Tiered Cache")

Figure 5: Cloudflare CDN with Tiered Cache and Regional Tiered Cache

### Argo Smart Routing

Argo Smart Routing is a service that finds optimized routes across the Cloudflare network to deliver responses to users more quickly. As discussed earlier, Cloudflare CDN leverages Argo Smart Routing to determine the best upper tier data centers for Tiered Cache.

In addition, Argo Smart Routing can be enabled to ensure the fastest paths over the Cloudflare network are taken between upper tier data centers and origin servers at all times. Without Argo Smart Routing, communication between upper tier data centers to origin servers are still intelligently routed around problems on the Internet to ensure origin reachability.

Argo Smart Routing accelerates traffic by taking into account real-time data and network intelligence from routing nearly 50 million HTTP requests per second; it ensures the fastest and most reliable network paths are traversed over the Cloudflare network to the origin server. On average, Argo Smart Routing accounts for 30% faster performance on web assets.

#### Traffic Flow: Tiered Cache, Smart Tiered Cache Topology with Argo Smart Routing

Figure 6 details the traffic flow when Tiered Cache and Argo Smart Routing are not enabled. The request comes into the closest data center, and, because content is not locally cached and Tiered Cache is not enabled, the request is sent directly to the origin server for the content. Also, since Argo Smart Routing is not enabled, a reliable, but perhaps not the fastest, path is taken when communicating with the origin server.

![Figure 6: Diagram with bidirectional arrows indicating a request between an end user and origin server without Argo Smart Routing enabled.](https://developers.cloudflare.com/_astro/ref-arch-cdn-figure6.CUGfxAW8_Z239rdF.svg "Figure 6: Cloudflare CDN without Tiered Cache or Argo Smart Routing")

Figure 6: Cloudflare CDN without Tiered Cache or Argo Smart Routing

Figure 7 articulates the traffic flow with both Tiered Cache and Argo Smart Routing enabled. When a request is received by Data Center 1 and there is a cache miss, the cache of the upper tier data center, Data Center 6, is checked. If the cached content is not found at the upper tier data center, with Argo Smart Routing enabled, the request is sent on the fastest path from the upper tier data center to the origin.

The fastest path is determined by the Argo network intelligence capabilities, which take into account real-time network data such as congestion, latency, and RTT.

**With the Cloudflare CDN, Argo Smart Routing is used when:**

1. There is a cache miss and the request needs to be sent to the origin server to retrieve the content.
2. There is a request for non-cacheable content, such as dynamic content (ex: APIs), and the request must go to the origin server.

![Figure 7: Diagram with bidirectional arrows indicating a request between an end user and origin server, with Argo Smart Routing enabled to improve speed.](https://developers.cloudflare.com/_astro/ref-arch-cdn-figure7.Cxfbf7KH_Z1eobh2.svg "Figure 7: Cloudflare CDN with Tiered Cache and Argo Smart Routing")

Figure 7: Cloudflare CDN with Tiered Cache and Argo Smart Routing

### Cache Reserve

Expanding on the idea of Tiered Cache, Cache Reserve further utilizes the scale and speed of the Cloudflare network while additionally leveraging R2, Cloudflare’s persistent object storage, to cache content even longer. Cache Reserve helps customers reduce bills by eliminating egress fees from origins while also providing multiple layers of resiliency and protection to make sure that content is reliably available which improves website performance by having content load faster. Basically, Cache Reserve is an additional higher tier of cache with longer retention duration.

While Cache Reserve can function without Tiered Cache enabled, it is recommended that Tiered Cache be enabled with Cache Reserve. Tiered Cache will funnel, and potentially eliminate, requests to Cache Reserve which eliminates redundant read operations and redundant storage of cached content reducing egress and storage fees. Enabling Cache Reserve via the Cloudflare dashboard will check and provide a warning if you try to use Cache Reserve without Tiered Cache enabled.

Cache Reserve has a retention period of 30 days which means it will hold cached content for 30 days regardless of cached headers or TTL policy. The TTL policy still affects the content’s freshness which means when content cache TTL expires inside of Cache Reserve, the content will need to be revalidated by checking the origin for any updates. The TTL policy can be set by any number of methods, such as Cache-Control, CDN-Cache-Control response headers, Edge Cache TTL, cache TTL by status code, or Cache Rules. Every time cache is read from Cache Reserve, the retention timer is reset to 30 days. After 30 days, if the cached content has not been read from Cache Reserve, the cache will be deleted.

There are three main criteria to match for content to be considered cacheable via Cache Reserve:

1. The content must be cacheable. See the [Cache documentation](https://developers.cloudflare.com/cache/) for more details on cacheable content.
2. TTL is set to at least 10 hours. This can be set by any method from the previous paragraph.
3. The Content-Length header must be used in the response header. Please note, this means that the \[Transfer-Method “chunked” will prevent Cache Reserve from being populated.

When combined with Tiered Caching and Argo Smart Routing, Cache Reserve can be a powerful tool for increasing cache hits and in turn reducing load on origin servers while also improving performance by bringing the content closer to the end user.

Note

Using [Image Resizing](https://developers.cloudflare.com/images/optimization/transformations/overview/) with Cache Reserve will not result in resized images being stored in Cache Reserve since Image Resizing takes place after reading from Cache Reserve. Resized images will be cached in other available tiers when they are served after resizing.

### Traffic flow: Cache Reserve topology

Figure 8 illustrates how Cache Reserve can help reduce load on an origin server while also helping repopulate cache stores in both upper and lower tier data centers.

![Figure 8: Traffic between end users and an origin server showing Cache Reserve as the final step in the architecture of the Cloudflare CDN solution.](https://developers.cloudflare.com/_astro/ref-arch-cdn-figure8.B8u-UV7X_Z239rdF.svg "Figure 8: Cloudflare CDN with Tiered Cache and Cache Reserve")

Figure 8: Cloudflare CDN with Tiered Cache and Cache Reserve

### China Network & Global Acceleration for clients in China

Latency depends not just on how far the client is from the origin or cache, but can also be significantly affected by the geographic region of the traffic — like China. To address these latency challenges, Cloudflare provides two key solutions:

1. [China Network](https://developers.cloudflare.com/china-network/) provides in-China caching for end users located in China, regardless of the origin location. This solution is provided by collaborating with JD Cloud and uses their data centers to ensure the fastest and most reliable cache performance for Chinese users compared to data centers outside of China.
2. [Global Acceleration](https://developers.cloudflare.com/china-network/concepts/global-acceleration/) offers reliable and secure connectivity to streamline content from origins to JD Cloud data centers in China. This is particularly beneficial for dynamic content like web applications and API calls.

## Summary

To summarize, the Cloudflare CDN is SaaS that helps address the challenges customers face around latency, performance, availability, redundancy, security, and costs. The Cloudflare CDN leverages Cloudflare’s global anycast network and Tiered Cache to deliver optimized results while saving costs for customers. Customers can also (enable Argo Smart)\[argo-smart-routing/get-started/\] Routing to ensure the fastest network path is used to route requests to the origin server and also choose to enable Cache Reserve to increase cache hits to further save costs and increase performance of their website or application.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/reference-architecture/","name":"Reference Architecture"}},{"@type":"ListItem","position":3,"item":{"@id":"/reference-architecture/architectures/","name":"Reference Architectures"}},{"@type":"ListItem","position":4,"item":{"@id":"/reference-architecture/architectures/cdn/","name":"Content Delivery Network (CDN) Reference Architecture"}}]}
```

---

---
title: CSAM Scanning Tool
description: Scan cached content for child sexual abuse material.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# CSAM Scanning Tool

The Child Sexual Abuse Material (CSAM) Scanning Tool allows website owners to proactively identify and take action on CSAM located on their website. By enabling this tool, Cloudflare will compare content served for your website through the Cloudflare cache to known lists of CSAM. These lists are provided to Cloudflare by leading child safety advocacy groups such as the National Center for Missing and Exploited Children (NCMEC).

Remember, by enabling the Service, you agree to the [Service-Specific Terms ↗](https://www.cloudflare.com/service-specific-terms-application-services/#csam-scanning-tool-terms) for the CSAM Scanning Tool. You agree to use this tool solely for the purposes of preventing the spread of CSAM.

---

## Why would a URL be blocked?

Because knowingly distributing or viewing CSAM is illegal, the owner of the website has enabled Cloudflare's CSAM scanning tool to proactively identify and block images identified as CSAM located on their website.

---

## Configure the CSAM scanning tool

To enable the tool:

1. Log into the [Cloudflare dashboard ↗](https://dash.cloudflare.com/).
2. Select your account and zone.
3. Go to **Caching** \> **Configuration**.
4. For **CSAM Scanning Tool**, select **Configure**.

You must provide an email address, which will be used to notify you in the event Cloudflare detects a positive match.

---

## What happens when a match is detected?

When a potential match is detected with the tool:

1. An email is sent to you once per day to inform you of any detections made in the past 24 hours. This email will include the file paths of any content that was matched.
2. If possible, a block is placed to prevent further serving of the matched content. If a block fails, we will indicate that the content has not been blocked in the email.

---

## What action should I take when a match is detected?

You are responsible for understanding and complying with any legal obligations you have as a website owner when made aware of any potential CSAM. Although legal obligations vary based on the provider and the jurisdiction, website owners often have obligations to report apparent CSAM, to remove content, and to preserve records. Some of those possible obligations are as follows:

* You likely have an obligation to report apparent CSAM to the appropriate authorities. You can file a report to NCMEC with additional information via NCMEC's CyberTip reporting form or find the preferred reporting portal for your jurisdiction via the INHOPE website.
  
* You may need to preserve and securely store a copy of the content and related data in the case NCMEC or law enforcement reach out for additional details.
* You likely have an obligation to securely preserve certain information related to your report for one year in the case of an investigation. To ensure that access to the content is limited, take care not to store this information anywhere accessible to anyone but those within your organization responsible for legal requests.
  
* You should remove the content and notify Cloudflare of the removal.
* Once any preservation obligations have been fulfilled, you should remove the content from your website. This is especially important if Cloudflare's notice to you indicates that our block was unsuccessful.

---

## How do I have a block removed from my website?

To disable a block, either because you have determined that the blocked content is not CSAM (a false positive) or because you have taken down the blocked content, view [Blocked Content in the Security Center](https://developers.cloudflare.com/fundamentals/reference/report-abuse/blocked-content/) in the Cloudflare Dashboard and request reviews on the relevant blocks. A request to remove a block must be accompanied by a representation from you confirming that the blocked content is not CSAM or has been removed.

These actions are available to users with the following roles:

* Admin
* Super Admin
* Trust & Safety

---

## Additional Resources

[CSAM Scanning Tool Supplemental Terms ↗](https://www.cloudflare.com/supplemental-terms/)

[National Center for Missing and Exploited Children (NCMEC) ↗](https://www.missingkids.org/)

[NCMEC CyberTipline ↗](https://www.missingkids.org/gethelpnow/cybertipline)

[INHOPE ↗](https://www.inhope.org/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/reference/csam-scanning/","name":"CSAM Scanning Tool"}}]}
```

---

---
title: Development Mode
description: Bypass the cache temporarily with Development Mode.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Development Mode

Development Mode temporarily suspends Cloudflare's edge caching and [Polish](https://developers.cloudflare.com/images/polish/) features for three hours unless disabled beforehand. Development Mode allows customers to immediately observe changes to their [cacheable content](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#default-cached-file-extensions) like images, CSS, or JavaScript.

Note

To bypass cache for longer than three hours, use bypass cache in [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#bypass-cache).

## Enable Development Mode

Development Mode temporarily bypasses Cloudflare's cache and does not purge cached files. To instantly purge your Cloudflare cache, refer to [purge cache](https://developers.cloudflare.com/cache/how-to/purge-cache/).

1. In the Cloudflare dashboard, go to the **Configuration** page.  
[ Go to **Configuration** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/configuration)
2. Toggle **Development Mode** to **On**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/reference/development-mode/","name":"Development Mode"}}]}
```

---

---
title: Using ETag Headers with Cloudflare
description: How ETag headers work with Cloudflare caching.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Using ETag Headers with Cloudflare

ETag headers identify whether the version of a resource cached in the browser is the same as the resource at the origin web server. A visitor's browser stores ETags. When a visitor revisits a site, the browser compares each ETag to the one it stored. Matching values cause a `304 Not-Modified HTTP` response that indicates the cached resource version is current. Cloudflare supports both strong and weak ETags configured at your origin web server.

## Weak ETags

Weak ETag headers indicate a cached resource is semantically equivalent to the version on the web server but not necessarily byte-for-byte identical.

Note

When using weak ETag headers, it is necessary to disable certain features such as [Email Obfuscation](https://developers.cloudflare.com/waf/tools/scrape-shield/email-address-obfuscation/) and [Automatic HTTPS Rewrites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/automatic-https-rewrites/) to prevent Cloudflare from removing the ETag headers set by your origin web server. For a comprehensive list of the features you need to disable, refer to the [Notes about end-to-end compression](https://developers.cloudflare.com/speed/optimization/content/compression/#notes-about-end-to-end-compression).

## Strong ETags

Strong ETag headers ensure the resource in browser cache and on the web server are byte-for-byte identical. Use [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/) to enable strong ETag headers.

### Behavior with Respect Strong ETags enabled

When you enable **Respect Strong ETags** in a cache rule, Cloudflare will use strong ETag header validation to ensure that resources in the Cloudflare cache and on the origin server are byte-for-byte identical.

However, in some situations Cloudflare will convert strong ETags to weak ETags. For example, given the following conditions:

* **Respect Strong ETags** is enabled
* [Brotli compression](https://developers.cloudflare.com/speed/optimization/content/compression/) is enabled
* The origin server's response includes an `etag: "foobar"` strong ETag header

The Cloudflare network will take the following actions, depending on the visitor's `accept-encoding` header and the compression used in the origin server's response:

| accept-encodingheader from visitor | Compression used in origin server response | Cloudflare actions                                                                                     |
| ---------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------ |
| gzip, br                           | GZIP                                       | Return GZIP-compressed response to visitor with strong ETag header: etag: "foobar".                    |
| gzip, br                           | Brotli                                     | Return Brotli-compressed response to visitor with strong ETag header: etag: "foobar".                  |
| br                                 | GZIP                                       | Decompress GZIP and return uncompressed response to visitor with weak ETag header: etag: W/"foobar".   |
| gzip                               | Brotli                                     | Decompress Brotli and return uncompressed response to visitor with weak ETag header: etag: W/"foobar". |
| gzip                               | (none)                                     | Return uncompressed response to visitor with strong ETag header: etag: "foobar".                       |
| gzip, br, zstd                     | Zstandard                                  | Return zstd-compressed response to visitor with strong ETag header: etag: "foobar".                    |
| gzip, br                           | Zstandard                                  | Decompress zstd and return br response to visitor with weak ETag header: etag: W/"foobar".             |
| zstd                               | Brotli/GZIP                                | Decompress zstd and return zstd response to visitor with weak ETag header: etag: W/"foobar".           |

Enabling **Respect Strong ETags** in Cloudflare automatically disables Rocket Loader, Email Obfuscation, and Automatic HTTPS Rewrites.

### Behavior with Respect Strong ETags disabled

When **Respect Strong ETags** is disabled, Cloudflare will preserve strong ETag headers set by the origin web server if all the following conditions apply:

* The origin server sends a response compressed using GZIP or Brotli, or an uncompressed response.
* If the origin server sends a compressed response, the visitor accepts the same compression (GZIP, Brotli), according to the `accept-encoding` header.
* [Rocket Loader](https://developers.cloudflare.com/speed/optimization/content/rocket-loader/) and [Email Obfuscation](https://developers.cloudflare.com/waf/tools/scrape-shield/email-address-obfuscation/) features are disabled.

In all other situations, Cloudflare will either convert strong ETag headers to weak ETag headers or remove the strong ETag. For example, given the following conditions:

* **Respect Strong ETags** is disabled
* [Brotli compression](https://developers.cloudflare.com/speed/optimization/content/compression/) is enabled
* The origin server's response includes an `etag: "foobar"` strong ETag header

The Cloudflare network will take the following actions, depending on the visitor's `accept-encoding` header and the compression used in the origin server's response:

| accept-encodingheader from visitor | Compression used in origin server response | Cloudflare actions                                                                                                                              |
| ---------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| gzip, br                           | GZIP                                       | Decompress GZIP and return Brotli-compressed response to visitor (since Brotli compression is enabled) with weak ETag header: etag: W/"foobar". |
| gzip, br                           | Brotli                                     | Return Brotli-compressed response to visitor with strong ETag header: etag: "foobar".                                                           |
| br                                 | GZIP                                       | Decompress GZIP and return Brotli-compressed response to visitor with weak ETag header: etag: W/"foobar".                                       |
| gzip                               | Brotli                                     | Decompress Brotli and return GZIP-compressed response to visitor with weak ETag header: etag: W/"foobar".                                       |
| gzip                               | (none)                                     | Compress origin response using GZIP and return it to visitor with weak ETag header: etag: W/"foobar".                                           |
| gzip, br, zstd                     | Zstandard                                  | Return zstd-compressed response to visitor with strong ETag header: etag: "foobar".                                                             |
| gzip, br                           | Zstandard                                  | Decompress zstd and return uncompressed response to visitor with weak ETag header: etag: W/"foobar".                                            |
| zstd                               | Brotli                                     | Decompress zstd and return uncompressed response to visitor with weak ETag header: etag: W/"foobar".                                            |

Refer to [Content compression](https://developers.cloudflare.com/speed/optimization/content/compression/) for more information.

## Important remarks

* You must set the value in a strong ETag header using double quotes (for example, `etag: "foobar"`). If you use an incorrect format, Cloudflare will remove the ETag header instead of converting it to a weak ETag.
* If a resource is cacheable and there is a cache miss, Cloudflare does not send ETag headers to the origin server. This is because Cloudflare requires the full response body to fill its cache.
* If your origin (or R2) applies compression based on `accept-encoding`, the first compression type will be cached. Consider whether strong ETags fit your use case, or use cache key rules to handle different compression types.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/reference/etag-headers/","name":"Using ETag Headers with Cloudflare"}}]}
```

---

---
title: Always Online
description: Troubleshoot Always Online cached page issues.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Always Online

Observe the following best practices when enabling Always Online with Internet Archive integration.

* **Allow requests from the Internet Archive IP addresses.** Origin servers receive requests from the Internet Archive IPs. Make sure you are not blocking requests from the Internet Archive IP range: `207.241.224.0/20` and `208.70.24.0/21`.
* **The Internet Archive does not consider your origin server's cache-control header.** When the Internet Archive is crawling sites, it will crawl sites regardless of their cache-control, since the Internet Archive does not cache assets, but archives them.
* **Consider potential conflicts with Cloudflare features that transform URIs.** Always Online with Internet Archive integration may cause issues with Cache Rules and other Cloudflare features that transform URIs due to the way the Internet Archive crawls pages to archive. Specifically, some redirects that take place at the edge may cause the Internet Archive's crawler not to archive the target URL. Before enabling Origin Cache Control, review [how Cloudflare caches resources by default](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/) as well as any Cache Rules you have configured so that you can avoid these issues. If you experience problems, disable Always Online.
* **Do not block Known Bots or Verified Bots via a WAF custom rule.** If you block either of these bot lists, the Internet Archive will not be able to crawl.

Do not use Always Online with:

* API traffic.
* An [IP Access rule](https://developers.cloudflare.com/waf/tools/ip-access-rules/) or a [WAF custom rule](https://developers.cloudflare.com/waf/custom-rules/) that blocks the United States or
* Bypass Cache cache rules. Always Online ignores Bypass Cache cache rules and serves Always Online cached assets.

## Limitations

There are limitations with the Always Online functionality:

1. Always Online is not immediately active for sites recently added due to:  
   * DNS record propagation, which can take 24-72 hours  
   * Always Online has not initially crawled the website
2. Cloudflare cannot show private content behind logins or handle form submission (POSTs) if your origin web server is offline.

Always Online does not trigger for HTTP response codes such as [404](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/4xx-client-error/error-404/), [503](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-503/), or [500](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-500/) errors such as database connection errors or internal server errors. This is because these status codes indicate the origin is reachable and responding — Always Online only activates when Cloudflare cannot connect to your origin at all (resulting in Cloudflare-generated [520–527](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-520/) status codes). If your origin returns a 5xx error, the origin is online by definition and Always Online will not intervene.

## Frequently asked questions

1. How can I know if a page has been crawled?  
   * You can go to the [Internet Archive ↗](https://web.archive.org/) and search for the page URL to see if it has been crawled or not.  
   * You can also check this via the [Internet Archive Availability API ↗](https://archive.org/help/wayback%5Fapi.php).
2. Why were not pages x, y, and z crawled?  
   * Since Cloudflare only requests to crawl the most popular pages on the site, it is possible that there will be missing pages. If you really want to archive a page, then you can visit the [Internet Archive ↗](https://web.archive.org/save) save page and ask them to crawl a particular page.
3. What IP addresses do we need to allowlist to make sure crawling works?  
   * IP Range: `207.241.224.0/20` and `208.70.24.0/21`. Note that this ip range belongs to Internet Archive and NOT Cloudflare, since it is the Internet Archive that does the crawling.
4. What user agent should the origin expect to see?  
   * Currently the Internet Archive uses: `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/605.1.15 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/605.1.15`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/troubleshooting/always-online/","name":"Always Online"}}]}
```

---

---
title: Dynamic content and login issues
description: Troubleshoot login failures, missing session cookies, and challenge loops caused by caching dynamic content.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Dynamic content and login issues

Dynamic pages such as login forms, checkout flows, and authenticated application routes can break when they are cached too aggressively.

Common symptoms include:

* Users can load the login page, but the sign-in form fails after submission.
* Sessions do not persist after a successful sign-in.
* The origin sends a `Set-Cookie` header, but the browser never stores the cookie.
* A challenge page appears, but after solving it the user returns to the login page or loses form state.

## Cached login page strips session cookies

One common cause is a [Cache Rule](https://developers.cloudflare.com/cache/how-to/cache-rules/) or legacy Page Rule configured to cache dynamic HTML.

This usually happens when all of the following are true:

* The page is configured as **Eligible for cache** or **Cache Everything**.
* The response is dynamic HTML such as `/login` or `/account`.
* The origin sends a `Set-Cookie` header.
* An [Edge TTL](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#edge-ttl) or status-code TTL overrides origin cache directives.

In this configuration, Cloudflare can cache the response and remove the `Set-Cookie` header before the response is stored at the edge. As a result, the browser receives the login page but never gets the session cookie required for the next request.

### How to confirm

Check the response for the login page or other dynamic route.

If you see both of the following, the page is probably cached when it should not be:

* `CF-Cache-Status: HIT` or `CF-Cache-Status: EXPIRED`
* No `Set-Cookie` header in the response, even though your origin usually sets one

You may also see framework-specific failures after form submission, for example:

* A redirect back to the login page
* A `403` or `500` after sign-in
* CSRF validation errors
* Missing server-side session state

This issue is common with frameworks that rely on a session or CSRF cookie on the first page load, including JavaServer Faces, ASP.NET, PHP session handlers, Django, Rails, and Laravel.

### Resolution

Do not cache login pages or other authenticated HTML.

Instead:

1. Restrict **Eligible for cache** or **Cache Everything** to static paths only.
2. Add a more specific Cache Rule that bypasses or disables caching for routes such as `/login`, `/account`, `/cart`, `/checkout`, and application API paths.
3. If the origin must control caching, remove any Edge TTL override that forces the page to be cached.
4. Verify the fixed response now returns `CF-Cache-Status: DYNAMIC`, `MISS`, or `BYPASS`, and preserves `Set-Cookie`.

For more information on cookie behavior, refer to [Interaction of Set-Cookie response header with Cache](https://developers.cloudflare.com/cache/concepts/cache-behavior/#interaction-of-set-cookie-response-header-with-cache).

## Challenge loops on login or form flows

Security challenges can also interrupt dynamic flows.

Two common patterns are:

* A challenge is triggered on the initial `GET` request for the login page. The user solves the challenge, but the application loses the original session or CSRF context.
* A challenge is triggered on the `POST` request that submits the login form or other sensitive action. The browser may have to repeat the request after the challenge, which can break the original form submission.

### How to confirm

Check whether a [WAF custom rule](https://developers.cloudflare.com/waf/custom-rules/), [managed rule](https://developers.cloudflare.com/waf/managed-rules/), or [rate limiting rule](https://developers.cloudflare.com/waf/rate-limiting-rules/) applies to the login path.

If the issue only affects routes such as `/login`, `/signin`, `/checkout`, or `/api/auth/*`, and the application works when the challenge is disabled for those paths, the challenge is likely interrupting the flow.

### Resolution

Use one of the following approaches:

1. Exclude the login or form submission path from the challenge rule.
2. Narrow the rule expression so it applies to suspicious traffic only.
3. If you must protect the route, use a less disruptive control on the page load and apply stronger actions elsewhere in the flow.

When debugging, also verify that rules are not matching Cloudflare-generated paths such as `/cdn-cgi/*`.

For more information on challenge-related behavior, refer to [Rules troubleshooting](https://developers.cloudflare.com/rules/reference/troubleshooting/) and [Cloudflare WAF troubleshooting](https://developers.cloudflare.com/waf/troubleshooting/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/troubleshooting/dynamic-content-and-login-issues/","name":"Dynamic content and login issues"}}]}
```

---

---
title: Issues with MP4 videos on iOS and Safari
description: Learn how to resolve issues with MP4 videos not playing on iOS and Safari.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Issues with MP4 videos on iOS and Safari

When traffic is proxied through Cloudflare, Safari on macOS and iOS devices may fail to load MP4 video files.

This issue occurs because Safari handles HTTP range requests differently than other browsers, particularly in how it processes ETags during video streaming.

Safari and iOS devices rely on HTTP range requests to support video features such as seeking to specific timestamps and resuming interrupted downloads.

When Cloudflare's caching layer processes these range requests with weak ETags, Safari may reject the cached response entirely, resulting in videos that fail to load or display as black screens.

To resolve this issue, configure two cache rules in the following order.

## 1\. Create the strong ETags rule

Create a [cache rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/) that applies to all MP4 files, marks them as eligible for cache, and turns on the Respect Strong ETags setting.

1. In the Cloudflare dashboard, go to the **Cache Rules** page.  
[ Go to **Cache Rules** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/cache-rules)
2. Select **Create rule** \> **Cache rules**.
3. Enter a descriptive name for the rule in **Rule name**.
4. In the **When incoming requests match…** section, create a filter that applies to all MP4 files, for example `URI Full` `Wildcard` `*.mp4`.
5. Select **Eligible for cache** in the **Cache eligibility** section.
6. Select **\+ Add Setting** for **Respect strong ETags** and turn on the toggle.
7. Select **Last** as **Place at**.

## 2\. Create the bypass cache rule

Create another cache rule that applies to all MP4 files and bypasses cache entirely.

1. In the Cloudflare dashboard, go to the **Cache Rules** page.  
[ Go to **Cache Rules** ](https://dash.cloudflare.com/?to=/:account/:zone/caching/cache-rules)
2. Select **Create rule** \> **Cache rules**.
3. Enter a descriptive name for the rule in **Rule name**.
4. In the **When incoming requests match…** section, create the same filter for MP4 files, for example `URI Full` `Wildcard` `*.mp4`.
5. Select **Bypass cache** in the **Cache eligibility** section.
6. Select **Last** as **Place at**.

## Why this order matters

The first rule preserves strong ETags for MP4 files, which satisfies Safari's requirements for range request handling. The second rule bypasses cache so that Cloudflare forwards range requests to the origin server instead of serving cached responses with potentially mismatched ETags.

The first rule must appear above the second rule in the Cache Rules list.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/troubleshooting/mp4-videos-on-ios-and-safari/","name":"Issues with MP4 videos on iOS and Safari"}}]}
```

---

---
title: Cloudflare China Network
description: Deliver secure, fast content in Mainland China through Cloudflare and JD Cloud data centers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare China Network

Delivering content quickly and securely to users in Mainland China requires infrastructure within China itself. Traffic routed through servers outside the country faces significant latency and reliability issues due to China's network boundaries.

The [Cloudflare China Network ↗](https://www.cloudflare.com/application-services/products/china-network/) solves this by running selected Cloudflare performance and security products on data centers located in Mainland China, operated by Cloudflare's partner JD Cloud. The data centers cover most populated regions in China.

You can use the same configurations and dashboard experience that you use with Cloudflare everywhere else in the world.

Chapters

* ![Introduction](https://customer-1mwganm1ma0xgnmj.cloudflarestream.com/b7933a5b3636ca29f834128ca92665b3/thumbnails/thumbnail.jpg?fit=crop&time=3s)  
 **Introduction** 3s
* ![How does it work?](https://customer-1mwganm1ma0xgnmj.cloudflarestream.com/b7933a5b3636ca29f834128ca92665b3/thumbnails/thumbnail.jpg?fit=crop&time=50s)  
 **How does it work?** 50s
* ![ICP regulations](https://customer-1mwganm1ma0xgnmj.cloudflarestream.com/b7933a5b3636ca29f834128ca92665b3/thumbnails/thumbnail.jpg?fit=crop&time=96s)  
 **ICP regulations** 1m36s
* ![China Express](https://customer-1mwganm1ma0xgnmj.cloudflarestream.com/b7933a5b3636ca29f834128ca92665b3/thumbnails/thumbnail.jpg?fit=crop&time=118s)  
 **China Express** 1m58s

## Main features

The Cloudflare China Network provides:

* A single solution for both performance improvement and security services such as [WAF](https://developers.cloudflare.com/waf/), [DDoS](https://developers.cloudflare.com/ddos-protection/), and [bot management](https://developers.cloudflare.com/bots/).
* A unified experience for managing network traffic and security posture. You can manage all configurations on the same dashboard.
* The same customer support capabilities as Cloudflare's global network. You may also have access to premium service and local language support.
* [In-China Authoritative DNS and in-China nameservers](https://developers.cloudflare.com/china-network/concepts/china-dns/) to reduce the time it takes for a user's browser to start receiving content (Time to First Byte).
* [Global Acceleration](https://developers.cloudflare.com/china-network/concepts/global-acceleration/), a suite of connectivity and performance offerings that simplify deploying your global assets in China.

## Availability

The Cloudflare China Network is available as a separate subscription for customers on an [Enterprise plan ↗](https://www.cloudflare.com/plans/enterprise/).

## Important notes

* Not all Cloudflare products are available in the Cloudflare China Network. Refer to [Available products and features](https://developers.cloudflare.com/china-network/reference/available-products/) for details.
* IPv6 support is mandatory for all Internet-facing services operating in Mainland China. The Cloudflare China Network automatically enables IPv6 on your domains to fulfill this requirement.
* All the content inside of Mainland China is monitored by local authorities and must comply with local regulations.
* You must have a valid [ICP (Internet Content Provider) filing or license](https://developers.cloudflare.com/china-network/concepts/icp/) for each apex domain you wish to onboard to Cloudflare.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/china-network/","name":"China Network"}}]}
```

---

---
title: Get started
description: Set up the Cloudflare China Network package on your Enterprise plan.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

## 1\. Contract required services and agree to supplemental terms

1. Ensure that you have a Cloudflare Enterprise plan. If you do not have an Enterprise plan yet, you must upgrade.
2. Add the Cloudflare China Network package (a separate subscription) to your Enterprise plan.
3. Agree to the [China Service Supplemental Terms ↗](https://www.cloudflare.com/supplemental-terms/#china-service).

Contact your sales team for more information on these steps.

## 2\. Obtain ICP and vet domain content

1. Obtain [Internet Content Provider filings or licenses](https://developers.cloudflare.com/china-network/concepts/icp/#obtain-an-icp-number) for all the apex domains you wish to onboard.
2. Present valid ICP filings or licenses for the zones you are onboarding.
3. Ensure that your websites [display their ICP number in the page footer](https://developers.cloudflare.com/china-network/concepts/icp/#display-your-icp-number).
4. Prepare the required information for JD Cloud to review your domains' content. JD Cloud, our partner, is required to review and vet the content of all domains on their network before China Network is enabled. You will need to provide the following information:  
   * Customer and company name  
   * Domain name  
   * ICP license/filing number  
   * A general description of the content of each domain (for example, Marketing website)  
   * A signed Self Attestation letter (provided by your sales team)

## 3\. Onboard your domains to the Cloudflare China Network

After content vetting is complete, [add your domains to Cloudflare](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/).

For first-time enablement of a zone, it will take approximately 24-48 hours to fully onboard to China Network. Afterwards, you can enable and disable China Network within your Cloudflare dashboard.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/china-network/","name":"China Network"}},{"@type":"ListItem","position":3,"item":{"@id":"/china-network/get-started/","name":"Get started"}}]}
```

---

---
title: Videos
description: Watch videos about Cloudflare China Network features and configuration.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Videos

[ Introduction to the China Network ](https://developers.cloudflare.com/learning-paths/china-network-overview/series/china-network-main-features-1/) Watch to learn how Cloudflare's China Network can help you improve performance, compliance, and connectivity for your users in Mainland China. 

[ Accelerate dynamic traffic outside of Mainland China ](https://developers.cloudflare.com/learning-paths/china-network-overview/series/china-express-overview-2/) Watch to learn more about Cloudflare's CDN Global Acceleration (formerly China Express). 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/china-network/","name":"China Network"}},{"@type":"ListItem","position":3,"item":{"@id":"/china-network/videos/","name":"Videos"}}]}
```

---

---
title: FAQ
description: Review FAQs for Cloudflare's China Network.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# FAQ

## Prerequisites and onboarding

### What are the requirements to enable Cloudflare China Network service from Cloudflare?

Refer to [Get started](https://developers.cloudflare.com/china-network/get-started/) for more information.

### Can I use my current account to access Cloudflare China Network service?

Yes, you can use your current Cloudflare account and dashboard.

### What are the requirements for requesting a Cloudflare China Network PoC?

Cloudflare requires that you have a valid [ICP (Internet Content Provider)](https://developers.cloudflare.com/china-network/concepts/icp/) number and content vetting approval from JD Cloud to provide you with a Cloudflare China Network PoC (Proof of Concept). If you are interested in a PoC, please contact your sales team.

## Data storage

### Will my Cloudflare account or configuration information be stored in China?

Cloudflare has taken numerous steps to ensure your security and the integrity of your data in China. Your identification information such as email addresses, password hashes, and billing information are never stored on Cloudflare China Network or shared with the Cloudflare partner except for Zone configuration information and bindings with Cloudflare’s Developer Suite which are stored on the China Network operated by our partners in China upon your enabling the China Service for a particular Zone.

## Compliance

### Does Cloudflare have an MIIT license to provide CDN services in China?

As a US company, Cloudflare does not have a license from China's Ministry of Industry and Information Technology (MIIT). However, Cloudflare's partner JD Cloud has all the licenses required by the MIIT to operate and provide CDN services in China.

### Can Cloudflare or JD Cloud help me to get the ICP?

No, neither Cloudflare nor JD Cloud is responsible for [ICP (Internet Content Provider)](https://developers.cloudflare.com/china-network/concepts/icp/) applications. However, Cloudflare can help provide referrals to ICP partners specialized in ICP applications. For more information, refer to [Obtain an ICP number](https://developers.cloudflare.com/china-network/concepts/icp/#obtain-an-icp-number).

### Why is my ICP filing/license revoked?

The application and revocation of ICP filings or licenses is managed by China's local authorities. Usually, either the customer or the agency processing the ICP application will receive a notification with more details. Cloudflare cannot provide the ICP revocation reasons.

### What would happen if my ICP filing/license got revoked?

Cloudflare's partner JD Cloud and the local authorities continuously track the status of the ICP. If your ICP gets revoked, JD Cloud may terminate or suspend your access to the China Service at any time and without liability, in accordance with China local regulations. To mitigate the impact on your Internet properties, Cloudflare will reroute the traffic for the affected domains to the nearest data centers outside of China.

### What is content vetting and why do I need JD Cloud to vet my domain's content before onboarding?

The JD Cloud network is proxying content inside of China for customers who have purchased Cloudflare China Network. To ensure compliance with China’s Internet regulations and with [JD Cloud's service terms ↗](https://docs.jdcloud.com/cn/product-service-agreement/starshield-terms-of-service), JD Cloud must review the content of all the domains before onboarding those domains to their network. They can approve or reject any domain based on the nature of its content. For more information, contact your sales team.

## Products and features

### How does IPv6 work on China Network?

All sites hosted in Mainland China must have IPv6 enabled. China Network automatically enables IPv6 for domains to fulfill this requirement and it is not possible to disable it. According to internal testing, IPv6 connections in Mainland China are more reliable and offer better latency.

### Is Turnstile available in Mainland China?

[Turnstile](https://developers.cloudflare.com/turnstile/) is not supported in Mainland China. Therefore, both China Network zones and [global zones](https://developers.cloudflare.com/fundamentals/concepts/accounts-and-zones/#zones) with users visiting your content from Mainland China may experience issues with Turnstile.

### Is Pages available in Mainland China?

[Pages](https://developers.cloudflare.com/pages/) is not available in Mainland China due to pages.dev certificate not residing within Mainland China. However, Pages from a global zone may potentially be extended into Mainland China.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/china-network/","name":"China Network"}},{"@type":"ListItem","position":3,"item":{"@id":"/china-network/faq/","name":"FAQ"}}]}
```

---

---
title: China Authoritative DNS
description: Resolve DNS queries in Mainland China to improve Time to First Byte performance.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# China Authoritative DNS

By default, Cloudflare China Network resolves each DNS request at the data center closest to the client. For clients outside of Mainland China, the closest global Cloudflare data center handles the request. For clients in Mainland China, a JD Cloud data center handles the request.

## In-China Nameserver

Cloudflare can deploy DNS service in Mainland China to improve Time to First Byte (TTFB) performance. With this option enabled, DNS queries resolve at data centers in Mainland China instead of at global DNS servers.

## When to use

Before you enable China Authoritative DNS, confirm that the majority (over 90%) of your traffic comes from Mainland China.

Warning

After you enable China Authoritative DNS, all DNS requests — including those from users outside of China — route to JD Cloud data centers in Mainland China instead of to the nearest global data center. This can increase latency for users outside of China.

## Comparison

The following table compares the default DNS offering with the In-China Nameserver option.

| DNS option   | Behavior                                      |
| ------------ | --------------------------------------------- |
| Default      | Uses the DNS server closest to the end user.  |
| In-China DNS | Uses only DNS in China, operated by JD Cloud. |

## General setup

After you [enable the Cloudflare China Network service](https://developers.cloudflare.com/china-network/get-started/), do the following:

1. Contact your Cloudflare sales team to enable the feature. Currently you cannot enable it in the Cloudflare dashboard.  
The current China Network supports both a [full setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/) and a [partial setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/).
2. Update your domain registrar with the assigned in-China nameservers.  
   * For a full setup: These nameservers are displayed in the Cloudflare dashboard.  
   * For a partial setup: Create a `CNAME` record pointing to `<hostname>.cdn.cloudflareanycast.net` for global default DNS setting and `<hostname>.cdn.cloudflarecn.net` for In-China DNS.  
Example 1: China Network zone named `example.cn` that requires In-China DNS  
If you have two DNS records, `www` and `media`, pointing to two different origin servers, your Authoritative DNS server will have the following DNS records:  
   * CNAME `www.example.cn` to `www.example.cn.cdn.cloudflarecn.net`  
   * CNAME `media.example.cn` to `media.example.cn.cdn.cloudflarecn.net`  
Example 2: China Network zone named `example.com` that requires global default DNS setting  
If you have two DNS records, `www` and `media`, pointing to two different origin servers, your Authoritative DNS server will have the following DNS records:  
   * CNAME `www.example.com` to `www.example.com.cdn.cloudflareanycast.net`  
   * CNAME `media.example.com` to `media.example.com.cdn.cloudflareanycast.net`
3. Test your configuration by checking if the domain resolves correctly.

For further assistance, contact your account team.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/china-network/","name":"China Network"}},{"@type":"ListItem","position":3,"item":{"@id":"/china-network/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/china-network/concepts/china-dns/","name":"China Authoritative DNS"}}]}
```

---

---
title: Global Acceleration
description: Simplify global asset deployment in China with connectivity from CMI, CBC Tech, and JD Cloud.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Global Acceleration

Note

Global Acceleration is a service offering that can be an add-on to China Network and also extends Zero Trust services into China.

Organizations that serve content or connect employees in Mainland China face connectivity challenges due to China's network infrastructure and regulatory requirements. Global Acceleration is a suite of connectivity offerings that address these challenges by providing optimized network paths into and out of China. Global Acceleration is provided by Cloudflare's partners including China Mobile International (CMI), CBC Tech, and JD Cloud.

Chapters

* ![Introduction](https://customer-1mwganm1ma0xgnmj.cloudflarestream.com/18457868eb13222051618b0d138e0225/thumbnails/thumbnail.jpg?fit=crop&time=17s)  
 **Introduction** 17s
* ![Dynamic content outside of Mainland China](https://customer-1mwganm1ma0xgnmj.cloudflarestream.com/18457868eb13222051618b0d138e0225/thumbnails/thumbnail.jpg?fit=crop&time=38s)  
 **Dynamic content outside of Mainland China** 38s
* ![Access to global services](https://customer-1mwganm1ma0xgnmj.cloudflarestream.com/18457868eb13222051618b0d138e0225/thumbnails/thumbnail.jpg?fit=crop&time=103s)  
 **Access to global services** 1m43s
* ![Private network connectivity](https://customer-1mwganm1ma0xgnmj.cloudflarestream.com/18457868eb13222051618b0d138e0225/thumbnails/thumbnail.jpg?fit=crop&time=174s)  
 **Private network connectivity** 2m54s
* ![Summary](https://customer-1mwganm1ma0xgnmj.cloudflarestream.com/18457868eb13222051618b0d138e0225/thumbnails/thumbnail.jpg?fit=crop&time=223s)  
 **Summary** 3m43s

Global Acceleration can support the following scenarios:

| Service                                                                                 | Scenario                                                                                           |
| --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| [CDN Global Acceleration](#cdn-global-acceleration)                                     | Improved performance for dynamic content (API responses, personalized pages) on China Network CDN. |
| [Cloudflare One Client Global Acceleration](#cloudflare-one-client-global-acceleration) | Cloudflare One Client used in Mainland China.                                                      |
| [Cloudflare WAN Global Acceleration](#cloudflare-wan-global-acceleration)               | Cloudflare WAN used in Mainland China.                                                             |
| [ICP](#icp-services)                                                                    | China Network prerequisite.                                                                        |
| [MLPS](#mlps-services)                                                                  | China cybersecurity compliance certification.                                                      |
| [Travel SIM](#travel-sim)                                                               | Temporary Cloudflare One Client access for employees traveling to Mainland China.                  |

## CDN Global Acceleration

CDN Global Acceleration provides stable and reliable connections for dynamic content — such as API responses and personalized pages — entering and exiting China, improving performance for users within the country.

## Cloudflare One Client Global Acceleration

Cloudflare One Client Global Acceleration (formerly WARP Global Acceleration) enables [Cloudflare One Client](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/cloudflare-one-client/) access within China, allowing remote employees to maintain secure and consistent connections.

## Cloudflare WAN Global Acceleration

Cloudflare WAN Global Acceleration (formerly Magic WAN Global Acceleration) enables [Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/) access within China, allowing in-office employees to maintain secure and reliable connectivity.

## ICP services

The Internet Content Provider (ICP) service simplifies the process of acquiring an [ICP filing or license](https://developers.cloudflare.com/china-network/concepts/icp/) for your domains. An ICP is a regulatory requirement for all websites operating in Mainland China.

## MLPS services

The Multi-Level Protection Scheme (MLPS) service add-on streamlines the process of obtaining MLPS Level 3 certification, a China cybersecurity compliance standard required for certain applications handling sensitive data.

## Travel SIM

Travel SIM offers temporary, seamless Cloudflare One Client access for individual employees traveling to China, ensuring uninterrupted connectivity during their visit.

---

## General process

### 1\. Validate prerequisites

Ensure that you have a Cloudflare [Enterprise plan ↗](https://www.cloudflare.com/plans/enterprise/) and [China Network](https://developers.cloudflare.com/china-network/), if you want CDN Global Acceleration. Cloudflare One Client and Cloudflare WAN entitlements are required for Cloudflare One Client Connection or Cloudflare WAN Global Acceleration.

### 2\. Sign contract

Contact your Cloudflare account team. They will assist you with contracting with us, or our local China partners, depending on the service.

### 3\. Deploy Global Acceleration

Our local China partners will assist you to deploy Global Acceleration.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/china-network/","name":"China Network"}},{"@type":"ListItem","position":3,"item":{"@id":"/china-network/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/china-network/concepts/global-acceleration/","name":"Global Acceleration"}}]}
```

---

---
title: Internet Content Provider (ICP)
description: Obtain and display an ICP license number required for websites operating in China.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Internet Content Provider (ICP)

To operate a website in China, you need government permission called an Internet Content Provider (ICP) number. Think of it as a permit — without one, your site can be shut down.

The ICP system is a licensing regime established by the Telecommunications Regulations of the People's Republic of China (中华人民共和国电信条例), introduced in September 2000.

Under the ICP regime, all websites with their own domain name that operate inside China must obtain a license. This applies whether the site is hosted on a server in Mainland China or delivered to visitors in China through a CDN. Licenses are issued at the provincial level. You can use the Ministry of Industry and Information Technology (MIIT) website to [check if a domain already has an ICP number ↗](https://beian.miit.gov.cn/#/Integrated/recordQuery) (only available in Chinese).

All public websites in Mainland China must have an ICP number [displayed on the website's home page](#display-your-icp-number). Websites with the same apex domain can share the same ICP number. China-based hosting providers are instructed to shut down any website (often without notice) without an ICP number.

## Types of ICP

To host web services in Mainland China, you are legally required to acquire an **ICP filing** or an **ICP license** in China. An ICP filing covers non-commercial (informational) sites, while an ICP license is required for sites that sell goods or services.

The type of ICP you must obtain depends on the type of website you are providing to customers in China:

| ICP filing         | ICP license                                                                                                                                                                                                   |                                                                                                                                                                                                      |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Definition         | An ICP filing, known in Chinese as “Bei’An,” is the first level of ICP registration. An ICP filing enables the holder to host a website on a server or CDN in Mainland China for informational purposes only. | An ICP license, known as “ICP Zheng” in Chinese, allows online platforms or third-party sellers selling goods and services to deploy their website on a hosting server or CDN within Mainland China. |
| Website Purpose    | Non-commercial and non-transactional purposes.                                                                                                                                                                | Commercial and transactional purposes.                                                                                                                                                               |
| Eligibility        | Representative officeWholly foreign-owned enterpriseJoint ventureLocal companyIndividuals (personal website)                                                                                                  | Joint venture (foreign company with less than 50% ownership)Local company                                                                                                                            |
| Example format     | Beijing ICP preparation XXXXXXXX number                                                                                                                                                                       | Beijing ICP license XXXXXXXX number                                                                                                                                                                  |
| Other requirements | N/A                                                                                                                                                                                                           | Companies acquiring an ICP license must already have obtained an ICP filing.                                                                                                                         |
| Timeline           | 1-2 months                                                                                                                                                                                                    | 2-3 months                                                                                                                                                                                           |

If you wish to host a marketing-related website, you only need an ICP filing.

---

## Obtain an ICP number

Cloudflare recommends that you apply for an ICP license through your hosting or cloud services provider, who will register the ICP number on your behalf. You will need to provide the following documents to your provider:

| For Individuals                                                                                                              | For Commercial Companies                                            |
| ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
| – ICP application form– Copy of your personal ID– Forms to authenticate website information– Copy of your domain certificate | – Copy of your business license– Your organization code certificate |

After all required documents are submitted, it can take four to eight weeks to obtain an ICP number, depending on the type of website and the province where the company is registered. Registration with the MIIT is free, but your provider may charge a processing fee.

After receiving the ICP number and the certificate, add it to your website's home page.

## Display your ICP number

After you obtain an ICP number, you must display it in the footer of your website, like in the following example:

![An ICP number displayed in the footer of a website.](https://developers.cloudflare.com/_astro/icp-number-in-footer.BX2CP_mf_1Ozdwp.webp) 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/china-network/","name":"China Network"}},{"@type":"ListItem","position":3,"item":{"@id":"/china-network/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/china-network/concepts/icp/","name":"Internet Content Provider (ICP)"}}]}
```

---

---
title: Available products and features
description: Cloudflare products and features supported on the China Network operated by JD Cloud.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Available products and features

The following products and features are available on the Cloudflare China Network operated by JD Cloud:

## Application Services

| Product/Feature                                                                                             | Description                                                                                                                                              |
| ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Authoritative DNS](https://developers.cloudflare.com/china-network/concepts/china-dns/)                    | Authoritative DNS resolution inside Mainland China.                                                                                                      |
| [CDN/Cache](https://developers.cloudflare.com/cache/)                                                       | Core cache features. Static cache only. Does not support Cache Reserve or Tiered Cache.                                                                  |
| [Image Transformations](https://developers.cloudflare.com/images/)                                          | Optimize image format at the edge to fit a domain's layout.                                                                                              |
| [DDoS Protection](https://developers.cloudflare.com/ddos-protection/)                                       | Layer 7 (application layer) protection against DDoS attacks such as HTTP flood attacks, WordPress Pingback attacks, HULK attacks, and LOIC attacks.      |
| [Managed rules](https://developers.cloudflare.com/waf/managed-rules/)                                       | Pre-configured OWASP rulesets and Cloudflare managed rulesets.                                                                                           |
| [Custom rules](https://developers.cloudflare.com/waf/custom-rules/)                                         | Custom WAF rules. Supports uploaded content scanning and managed challenges.                                                                             |
| [Rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/)                           | Define rate limits for incoming requests matching an expression, and the action to take when those rate limits are reached.                              |
| [Content scanning](https://developers.cloudflare.com/waf/detections/malicious-uploads/)                     | Attempts to detect content objects, such as uploaded files, and scans them for malicious signatures like malware.                                        |
| [Client-side security](https://developers.cloudflare.com/client-side-security/) (formerly Page Shield)      | Simplifies external script management by tracking loaded resources like scripts and providing alerts when it detects new resources or malicious scripts. |
| [Bot Management](https://developers.cloudflare.com/bots/)[1](#user-content-fn-1)                            | Provides bot identification and protection for a domain. Only supports certain Machine Learning (ML) models.                                             |
| [Argo Smart Routing](https://developers.cloudflare.com/argo-smart-routing/)                                 | Layer 7 (application layer) traffic smart-routed more efficiently to origin.                                                                             |
| [Rules](https://developers.cloudflare.com/rules/)[2](#user-content-fn-2)                                    | Make adjustments to requests and responses, configure Cloudflare settings, and trigger specific actions for matching requests.                           |
| [Load Balancing](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-china/) | Maximize application performance and availability.                                                                                                       |

## Developer Services

| Product/Feature                                                                                            | Description                                                                                                                                        |
| ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Workers](https://developers.cloudflare.com/workers/)                                                      | A serverless execution environment running on the Cloudflare global network.                                                                       |
| [Workers KV](https://developers.cloudflare.com/kv/)                                                        | Configuration data, service routing metadata, personalization (A/B testing).                                                                       |
| [R2](https://developers.cloudflare.com/r2/)[3](#user-content-fn-3)                                         | Object storage for all your data.                                                                                                                  |
| [Assets](https://developers.cloudflare.com/workers/static-assets/)                                         | Upload static assets (HTML, CSS, images and other files) as part of your Worker — Cloudflare will handle caching and serving them to web browsers. |
| [Environment variables](https://developers.cloudflare.com/workers/configuration/environment-variables/)    | Attach text strings or JSON values to your Worker.                                                                                                 |
| [Images](https://developers.cloudflare.com/images/optimization/binding/)[4](#user-content-fn-4)            | Store, transform, optimize, and deliver images at scale.                                                                                           |
| [mTLS](https://developers.cloudflare.com/workers/runtime-apis/bindings/mtls/)                              | Securely connect to backend servers over [mTLS ↗](https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/).                      |
| [Rate Limiting](https://developers.cloudflare.com/workers/runtime-apis/bindings/rate-limit/)               | Define rate limits and write code around them in your Worker.                                                                                      |
| [Secrets](https://developers.cloudflare.com/workers/configuration/secrets/)                                | Attach encrypted text values to your Worker.                                                                                                       |
| [Service bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/)      | Service bindings allow one Worker to call into another, without going through a publicly-accessible URL.                                           |
| [Tail Workers](https://developers.cloudflare.com/workers/observability/logs/tail-workers/)                 | Receives information about the execution of other Workers.                                                                                         |
| [Version metadata](https://developers.cloudflare.com/workers/runtime-apis/bindings/version-metadata/)      | Access metadata associated with a version from inside the Workers runtime.                                                                         |
| [Workers for Platforms](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/) | Deploy custom code on behalf of your users or let your users directly deploy their own code to your platform, managing infrastructure.             |

## Network Services

| Feature                                                                           | Description                                                                                                 |
| --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| [IPv6](https://developers.cloudflare.com/network/ipv6-compatibility/)             | All data centers have IPv6 support by default.                                                              |
| [SSL/TLS](https://developers.cloudflare.com/ssl/)                                 | Customer Certificate, Dedicated Certificate, Universal Certificate, Custom, ACM (Dedicated), Universal SSL. |
| [HTTP/3 (QUIC) ↗](https://www.cloudflare.com/learning/performance/what-is-http3/) | The latest version of the HTTP protocol to optimize page loading performance.                               |
| [WebSockets](https://developers.cloudflare.com/workers/runtime-apis/websockets/)  | Real-time communication with Cloudflare Workers serverless functions.                                       |

## Zero Trust Services

Refer to [Global Acceleration](https://developers.cloudflare.com/china-network/concepts/global-acceleration/) for more information.

## Other Services

| Feature                                                              | Description                                                      |
| -------------------------------------------------------------------- | ---------------------------------------------------------------- |
| [Instant Logs](https://developers.cloudflare.com/logs/instant-logs/) | Live Tail your Cloudflare HTTP logs in the Cloudflare dashboard. |
| [Logpush](https://developers.cloudflare.com/logs/logpush/)           | Push your Cloudflare HTTP logs to a storage service.             |

For more details or specific product features, refer to the [FAQ](https://developers.cloudflare.com/china-network/faq/#products-and-features) page or contact your account team.

## Footnotes

1. [Turnstile](https://developers.cloudflare.com/turnstile/) is not available within Mainland China. [↩](#user-content-fnref-1)
2. [Origin Rules](https://developers.cloudflare.com/rules/origin-rules/) require that China Network is enabled on both the original zone (the one visitors are accessing) and the target zone. Otherwise, visitors will receive a [1016 error](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-1xxx-errors/error-1016/) along with an [HTTP 530 status code](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-530/). [↩](#user-content-fnref-2)
3. R2 buckets cannot be created within Mainland China and [custom domains](https://developers.cloudflare.com/r2/buckets/public-buckets/#add-your-domain-to-cloudflare) are not supported within Mainland China. However, R2 can be extended into Mainland China through [Global Acceleration](https://developers.cloudflare.com/china-network/concepts/global-acceleration/). [↩](#user-content-fnref-3)
4. Image Resizing works [within Workers](https://developers.cloudflare.com/images/optimization/transformations/transform-via-workers/), but may not be available [through URL format](https://developers.cloudflare.com/images/optimization/features/). [↩](#user-content-fnref-4)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/china-network/","name":"China Network"}},{"@type":"ListItem","position":3,"item":{"@id":"/china-network/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/china-network/reference/available-products/","name":"Available products and features"}}]}
```

---

---
title: Infrastructure
description: China data center locations, network IP addresses, and API endpoints.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Infrastructure

## China data centers

For up-to-date information, refer to the [Cloudflare China Network ↗](https://www.cloudflare.com/china-network/) page.

### Network IP addresses

Cloudflare publishes a list of IP addresses for JD Cloud data centers, used by Cloudflare when connecting to the origin networks of customers to retrieve assets. These addresses are not the same IP addresses returned to website visitors as part of DNS resolution.

You can obtain the list of JD Cloud data center IP addresses via Cloudflare API. Use the [Cloudflare/JD Cloud IP Details](https://developers.cloudflare.com/api/resources/ips/methods/list/) operation with the `networks=jdcloud` query string parameter:

Cloudflare/JD Cloud IP Details

```

curl "https://api.cloudflare.com/client/v4/ips?networks=jdcloud" \

  --request GET


```

```

{

  "result": {

    "ipv4_cidrs": [

      // (...)

    ],

    "ipv6_cidrs": [

      // (...)

    ],

    "jdcloud_cidrs": [

      // (...)

    ],

    "etag": "<ETAG>"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

The `jdcloud_cidrs` array lists the IP addresses of JD Cloud data centers.

Cloudflare will add new IP addresses to this list 30 days in advance before connecting from those IP addresses to an origin server. If you are using the China Network on JD Cloud, you should update your firewalls to reflect any IP address changes at least once every 30 days.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/china-network/","name":"China Network"}},{"@type":"ListItem","position":3,"item":{"@id":"/china-network/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/china-network/reference/infrastructure/","name":"Infrastructure"}}]}
```

---

---
title: Cloudflare DNS
description: Manage DNS records, nameservers, and DNSSEC with Cloudflare DNS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare DNS

Leverage Cloudflare's global network to deliver excellent performance and reliability to your domain.

 Available on all plans 

Cloudflare DNS is a fast, resilient, and easy-to-manage authoritative DNS service. It delivers excellent performance and reliability to your domain while also protecting your business from [DDoS attacks ↗](https://www.cloudflare.com/learning/ddos/what-is-a-ddos-attack/) and [route leaks and hijacking ↗](https://www.cloudflare.com/learning/security/glossary/bgp-hijacking/). To know where to begin, refer to [Get started](https://developers.cloudflare.com/dns/get-started/).

Enterprise customers can also use Cloudflare DNS for their private network with [Internal DNS (Beta)](https://developers.cloudflare.com/dns/internal-dns/) and proxy public hostnames to [private origins (Beta)](https://developers.cloudflare.com/dns/private-origins/).

---

## Features

###  DNS records 

DNS records make resources available on your domain, and allow you to configure services such as email.

[ Use DNS records ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) 

###  DNSSEC 

DNS Security Extensions (DNSSEC) adds cryptographic signatures to your DNS records, preventing anyone else from redirecting traffic intended for your domain.

Cloudflare also supports [Multi-signer DNSSEC](https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/).

[ Use DNSSEC ](https://developers.cloudflare.com/dns/dnssec/) 

###  CNAME flattening 

CNAME flattening delivers better performance and allows you to add a CNAME record at your apex domain (`example.com`). Paid accounts can choose to flatten all CNAME records on their domain.

[ Use CNAME flattening ](https://developers.cloudflare.com/dns/cname-flattening/) 

  
Refer to [DNS features and availability](https://developers.cloudflare.com/dns/reference/all-features/) for a complete list of features and their availability according to different Cloudflare plans.

---

## Related products

**[Registrar](https://developers.cloudflare.com/registrar/)** 

Before you can start using Cloudflare DNS you must first have a domain. Buy and renew your domain at cost with Cloudflare Registrar.

**[DNS Resolver](https://developers.cloudflare.com/1.1.1.1/)** 

Cloudflare DNS focuses on businesses and their domain administration. If you are a consumer and want a more private way to browse the Internet, check out 1.1.1.1, Cloudflare's public DNS Resolver.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}}]}
```

---

---
title: Get started
description: Set up Cloudflare DNS for your domain.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

You can use Cloudflare DNS with a variety of [setups](https://developers.cloudflare.com/dns/zone-setups/). For an overview of what these setups are and an introduction to specific DNS terminology, refer to [Concepts](https://developers.cloudflare.com/dns/concepts/).

In the most common setup (full), you [add your domain](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/), import your [DNS records](https://developers.cloudflare.com/dns/manage-dns-records/), and [update your nameservers](https://developers.cloudflare.com/dns/nameservers/update-nameservers/) to make Cloudflare your primary authoritative DNS provider.

Note

Make sure to [review your DNS records](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/#2-review-your-dns-records) before updating your nameservers. If you activate your domain on Cloudflare _without_ setting up the correct DNS records, your domain may not be reachable.

Once the setup is completed:

* You [manage DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) through the Cloudflare dashboard or API. This is how you control which resources are available on the apex domain (`example.com`) or specific subdomains (`blog.example.com`) of your website, as well as control other configurations.
* Cloudflare [responds to all DNS queries](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/) for your hostnames and your DNS records are propagated across the [Cloudflare global network ↗](https://www.cloudflare.com/network/), speeding up your domain.

## Resources

The following links introduce important concepts and will guide you through actions you may need to take while having your website or application on Cloudflare.

* [DNS records](https://developers.cloudflare.com/dns/manage-dns-records/): DNS records contain information about your domain and are used to make your website or application available to visitors and other web services.
* [Nameservers](https://developers.cloudflare.com/dns/nameservers/): In the context of Cloudflare DNS, nameservers refer to authoritative nameservers. When a nameserver is authoritative for `example.com`, it means that DNS resolvers will consider responses from this nameserver when a user tries to access `example.com`.
* [Proxy status](https://developers.cloudflare.com/dns/proxy-status/): Proxy status affects how Cloudflare treats incoming HTTP/S requests to A, AAAA, and CNAME records. When a record is proxied, Cloudflare responds with [anycast IPs](https://developers.cloudflare.com/fundamentals/concepts/cloudflare-ip-addresses/), which speeds up and protects HTTP/S traffic with our [cache](https://developers.cloudflare.com/cache/)/[CDN ↗](https://www.cloudflare.com/learning/cdn/what-is-a-cdn/), [DDoS protection](https://developers.cloudflare.com/ddos-protection/), [WAF](https://developers.cloudflare.com/waf/), and [more](https://developers.cloudflare.com/directory/?product-group=Application+performance%2CApplication+security).

## Further reading

* [How Cloudflare works](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/): An overview of how Cloudflare works as a DNS provider and as a reverse proxy.
* [DNS analytics](https://developers.cloudflare.com/dns/additional-options/analytics/): An overview of the different data sources and insights you can get when using Cloudflare DNS.
* [Troubleshooting](https://developers.cloudflare.com/dns/troubleshooting/): A full resources list for when something is not working.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/get-started/","name":"Get started"}}]}
```

---

---
title: Concepts
description: Understand key DNS concepts with Cloudflare's technical documentation. Learn about nameservers, DNS records, DNSSEC, and more.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Concepts

The Domain Name System (DNS) translates human-readable domain names (like `example.com`) into IP addresses that computers use to locate each other on the Internet. This page covers key DNS concepts used throughout the Cloudflare DNS documentation. For more concepts and broader descriptions, refer to the [Cloudflare Learning Center ↗](https://www.cloudflare.com/learning/dns/what-is-dns/).

## Domain

Also known as domain name, a domain is the string of text that identifies a specific website, such as `google.com` or `facebook.com`. Every time you access a website from your web browser, a DNS query (a lookup request to translate the domain into an address) takes place and the DNS service maps the domain to the actual IP address where the website is [hosted](https://developers.cloudflare.com/fundamentals/manage-domains/).

## Registrar

Before you can start using the Cloudflare DNS service, you must first have a domain. You obtain a domain through a registrar, a service that handles the reservation of domain names as explained in the [Learning Center ↗](https://www.cloudflare.com/learning/dns/glossary/what-is-a-domain-name-registrar/).

Very often the same company that offers domain registration also offers web hosting and DNS management.

You can register a domain name at cost (without markup fees) through [Cloudflare Registrar](https://developers.cloudflare.com/registrar/). Every domain acquired through Cloudflare Registrar must also use Cloudflare as their [primary authoritative DNS](#authoritative-dns).

## Nameserver

DNS resolution — the process of translating a domain name into an IP address — involves several types of servers. In this documentation, nameserver usually refers to the Cloudflare authoritative nameservers, the servers that hold the definitive DNS records for your domain and provide the final answer in DNS resolution. For more context on the different server types involved, refer to the [article about DNS server types ↗](https://www.cloudflare.com/learning/dns/dns-server-types/).

Refer to [Nameservers](https://developers.cloudflare.com/dns/nameservers/) for details on the different nameserver offerings.

## Authoritative DNS

Authoritative DNS refers to the service whose nameservers provide the final answer mapping a hostname (such as `example.com` or `blog.example.com`) to the IP address that hosts the corresponding content or resources.

The speed and reliability of your authoritative DNS service directly affects how available, resilient, and responsive your website or application is. If the authoritative DNS is slow or unreachable, visitors may not be able to reach your site. Cloudflare DNS is an authoritative DNS service that runs on Cloudflare's global network, distributing DNS answers from data centers worldwide. Refer to [How Cloudflare works](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/) for details.

## DNS setups

It is also possible that one same company will use more than one DNS provider. Usually, this relates to making a domain more resilient - if one provider faces an outage, the nameservers operated by the other DNS provider will most likely still be available.

In this context, you can have a primary DNS setup, when you use Cloudflare to manage your [DNS records](#dns-records), or a [secondary DNS setup](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/), when your DNS records are managed on a different provider and Cloudflare simply receives zone transfers containing your DNS records.

When you have a primary DNS setup, you can either use only Cloudflare (also known as [Full setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/)), or you can use Cloudflare and another provider, where the other provider is the one to receive [outgoing zone transfers](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-primary/) from Cloudflare.

Finally, as Cloudflare also works as a [reverse proxy](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/#cloudflare-as-a-reverse-proxy), you can use a [CNAME setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/) (also known as partial) when you do not want Cloudflare to be [authoritative](#authoritative-dns) for your domain but you still want to proxy individual subdomains through Cloudflare.

## DNS records

DNS records are instructions that live in the authoritative DNS servers and provide information about a [zone](#zone). This includes what IP address is associated with a particular domain, but can also cover many other use cases, such as directing emails to a mail server or validating ownership of a domain.

For more details about using DNS records within Cloudflare, refer to [Manage DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) and [DNS record types](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/).

## Zone

A DNS zone is an administrative boundary that defines who controls the DNS records for a given domain and its subdomains. For example, the zone for `example.com` contains the records for `example.com` and its subdomains like `blog.example.com`. Read more in the ["What is a DNS zone?" Learning Center article ↗](https://www.cloudflare.com/learning/dns/glossary/dns-zone/).

Each domain added to a Cloudflare account is listed on the account home page as a zone. The exact properties and behaviors of your zone depend on its [DNS setup](https://developers.cloudflare.com/dns/zone-setups/).

Different Cloudflare products and features are configurable at the zone level. Refer to [Fundamentals](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) for details.

### Zone apex

The zone apex is the highest-level domain within a zone — the starting point from which all DNS records in that zone are managed.

In most cases, the zone apex is the same as the apex domain (for example, `example.com`). However, with [subdomain delegation](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/) (available on Enterprise plans), a subdomain like `sub.example.com` can be its own zone, making that subdomain the zone apex.

Example 1

DNS management for **example.com**:

| Type | Name | Content   | Proxy status | TTL  |
| ---- | ---- | --------- | ------------ | ---- |
| A    | blog | 192.0.2.1 | Proxied      | Auto |

Zone apex: `example.com`

Full record name: `blog.example.com`

Example 2

DNS management for **sub.example.com**:

| Type | Name | Content   | Proxy status | TTL  |
| ---- | ---- | --------- | ------------ | ---- |
| A    | blog | 192.0.2.1 | Proxied      | Auto |

Zone apex: `sub.example.com`

Full record name: `blog.sub.example.com`

To create a DNS record at the zone apex, use `@` for the record **Name**. The `@` symbol is a DNS convention that represents the zone apex itself. For details, refer to [Create zone apex record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-zone-apex/).

Record at the zone apex

DNS management for **example.com**:

| Type | Name | Content   | Proxy status | TTL  |
| ---- | ---- | --------- | ------------ | ---- |
| A    | @    | 192.0.2.1 | Proxied      | Auto |

Zone apex: `example.com`

Full record name: `example.com`

DNS management for **sub.example.com**:

| Type | Name | Content   | Proxy status | TTL  |
| ---- | ---- | --------- | ------------ | ---- |
| A    | @    | 192.0.2.1 | Proxied      | Auto |

Zone apex: `sub.example.com`

Full record name: `sub.example.com`

## DNSSEC

Without additional protection, DNS responses can be spoofed — an attacker could return a forged response and redirect visitors to a malicious site. DNSSEC (DNS Security Extensions) addresses this by adding cryptographic signatures to DNS records. These signatures can then be checked to verify that a record came from the correct DNS server, preventing anyone else from issuing false DNS records on your behalf and redirecting traffic intended for your domain. You can read more about it in the [article about DNS security ↗](https://www.cloudflare.com/learning/dns/dns-security/).

For help setting up DNSSEC in Cloudflare, refer to [Enable DNSSEC](https://developers.cloudflare.com/dns/dnssec/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/concepts/","name":"Concepts"}}]}
```

---

---
title: DNS setups
description: Available DNS zone setup types and how to configure them.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNS setups

When using Cloudflare DNS, you have a few options for your DNS zone setup:

* [Primary setup (Full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/) (most common): Use Cloudflare as your primary DNS provider and manage your DNS records on Cloudflare.
* [CNAME setup (Partial)](https://developers.cloudflare.com/dns/zone-setups/partial-setup/): Keep your primary DNS provider and only use Cloudflare's reverse proxy for individual subdomains.
* [Zone transfers](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/): Use Cloudflare and another DNS provider together across your entire zone to increase availability and fault tolerance. DNS records will be transferred between providers using [AXFR ↗](https://datatracker.ietf.org/doc/html/rfc5936) or [IXFR ↗](https://datatracker.ietf.org/doc/html/rfc1995).
* [Subdomain setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/): With your apex domain (`example.com`) on a CNAME setup (partial) or primary setup (full), independently manage the settings for a delegated subdomain (`blog.example.com`) within a separate zone and, potentially, a separate account.  
When configuring a subdomain setup, its availability will depend on both the parent zone setup and the setup used for the child zone. A child zone holds DNS management for a delegated subdomain.  
| Parent zone                                                                                                                                                                     | Child zone                                                                                             | Available |  
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | --------- |  
| [Full](https://developers.cloudflare.com/dns/zone-setups/full-setup/) or [Secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) | [Full](https://developers.cloudflare.com/dns/zone-setups/full-setup/)                                  | Yes       |  
| [Full](https://developers.cloudflare.com/dns/zone-setups/full-setup/) or [Secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) | [Secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) | Yes       |  
| [Full](https://developers.cloudflare.com/dns/zone-setups/full-setup/) or [Secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) | [Partial](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)                            | No        |  
| [Partial](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)                                                                                                     | [Full](https://developers.cloudflare.com/dns/zone-setups/full-setup/)                                  | Yes       |  
| [Partial](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)                                                                                                     | [Secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) | Yes       |  
| [Partial](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)                                                                                                     | [Partial](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)                            | Yes       |  
    
For details, refer to [setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/setup/).

---

## Zone status

The possible statuses for a zone are the following:

* Initializing
* Pending
* Active
* Moved
* Deleted
* Purged

For details on each status and how a zone can transition from one status to the other, consider the [Reference page](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/).

Do not use pending zones in production

If you have a paid plan, make sure not to use pending zones for production traffic. Cloudflare responds to DNS queries for pending zones on the assigned Cloudflare nameserver IPs but there are associated risks, especially if you do not use [zone holds](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/).

---

## Common use cases and availability

If you are unsure of which setup to use, consider the questions below for an overview of common use cases and their correspondence to each setup and [different pricing plans ↗](https://www.cloudflare.com/plans/#overview).

Are you on a Free or Pro plan?

If you are on a Free or Pro plan, [primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/) is the only one available. This is the recommended and most common option.

Will you be using Cloudflare with other DNS providers?

If you are on a Business or Enterprise plan, you can use [CNAME setup (partial)](https://developers.cloudflare.com/dns/zone-setups/partial-setup/) to keep your primary DNS provider and only proxy individual subdomains through Cloudflare.

If you are on an Enterprise plan, you also have the option to use [zone transfers](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/) to set up Cloudflare as either a primary or a secondary DNS provider.

Do you need to manage subdomains separately?

If you are on an Enterprise plan, you can use [subdomain setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/) to manage the Cloudflare settings for one or more subdomains separately from your domain apex.

Note

If you run your own authoritative nameservers but still want to benefit from Cloudflare's global anycast network, check out [DNS Firewall](https://developers.cloudflare.com/dns/dns-firewall/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}}]}
```

---

---
title: Convert full setup to partial setup
description: Convert a full DNS setup to a partial CNAME setup.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Convert full setup to partial setup

If you initially configured a [primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/), you can later convert your zone to use a CNAME setup (also known as partial setup). This guide assumes your zone is already in an [active status](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/#active).

A CNAME setup allows you to use [Cloudflare's reverse proxy](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/) on individual subdomains while using a different authoritative DNS provider.

---

## Before you begin

### Consider CNAME setup limitations

* A CNAME setup requires a CNAME record for each proxied hostname but, following [RFC 1912 ↗](https://datatracker.ietf.org/doc/html/rfc1912#section-2.4), CNAME records are not allowed on the zone apex (`example.com`). With a CNAME setup, you can only proxy the zone apex if your authoritative DNS provider supports [CNAME flattening ↗](https://blog.cloudflare.com/introducing-cname-flattening-rfc-compliant-cnames-at-a-domains-root/) (or an equivalent like ALIAS/ANAME records), or if you create A/AAAA records pointing the apex directly to Cloudflare [anycast IP addresses](https://developers.cloudflare.com/fundamentals/concepts/cloudflare-ip-addresses/). Otherwise, you can only proxy subdomains.  
Warning  
Cloudflare only recommends the A/AAAA approach if you use [Static IPs](https://developers.cloudflare.com/byoip/concepts/static-ips/) or [Bring Your Own IP (BYOIP)](https://developers.cloudflare.com/byoip/), because standard Cloudflare anycast IPs can change.
* Once your zone is using CNAME setup, on the dashboard, you will only be able to create A, AAAA, and CNAME records, which are the DNS record types that can be [proxied](https://developers.cloudflare.com/dns/proxy-status/).

### Plan for SSL/TLS certificates

Universal SSL deletion

If you are using [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/), converting to a CNAME setup will delete your existing Universal SSL certificates.

New Universal SSL certificates will be [provisioned](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/enable-universal-ssl/#partial-dns-setup) for your proxied subdomains only after each CNAME record pointing to `{your-hostname}.cdn.cloudflare.net` is in place, and domain ownership is verified with the TXT record, as [explained below](#2-convert-the-zone).

To avoid downtime, replace your Universal SSL certificates with an [advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/), which will persist during the transition. After the conversion, you can optionally configure [delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/#setup).

---

## 1\. Prepare new DNS provider

1. Export a zone file  
   * [ Dashboard ](#tab-panel-7979)  
   * [ API ](#tab-panel-7980)  
To export records using the dashboard:  
   1. In the Cloudflare dashboard, go to the **DNS Records** page.  
   [ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)  
   2. Select **Import and Export**.  
   3. Select **Export**.  
To export records using the API, send a [GET request](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/export/).  
Required API token permissions  
At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:  
   * `DNS Read`  
   * `DNS Write`  
Export DNS Records  
```  
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/export" \  
  --request GET \  
  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"  
```
2. Import the zone file into your new primary DNS provider.
3. At your new authoritative DNS provider, create or update records so that you have CNAME records pointing to `{your-hostname}.cdn.cloudflare.net` for every hostname you wish to proxy through Cloudflare.  
Example CNAME record at authoritative DNS provider  
The CNAME record for `www.example.com` would be:  
```  
www.example.com CNAME www.example.com.cdn.cloudflare.net  
```

## 2\. Convert the zone

* [ Dashboard ](#tab-panel-7977)
* [ API ](#tab-panel-7978)

1. On the Cloudflare dashboard, go to the zone's **Overview** page.
2. Select **Convert to CNAME DNS Setup** and then **Convert** to confirm.
3. Save the information from the **Verification TXT Record** and add the record at your new authoritative DNS provider. If you lose the information, you can also access it on the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page, under **Verification TXT Record**.  
Example verification record  
A verification record for `example.com` might be:  
| Type | Name                          | Content             |  
| ---- | ----------------------------- | ------------------- |  
| TXT  | cloudflare-verify.example.com | 966215192-518620144 |

1. Use the [Edit Zone endpoint](https://developers.cloudflare.com/api/resources/zones/methods/edit/) with `type` set to `partial` to convert the zone type.
2. Take note of the value returned under `verification_key` in the API response and add the corresponding TXT record at your new authoritative DNS provider.  
Example verification record  
A verification record for `example.com` might be:  
| Type | Name                          | Content             |  
| ---- | ----------------------------- | ------------------- |  
| TXT  | cloudflare-verify.example.com | 966215192-518620144 |

Note

If your authoritative DNS provider automatically appends DNS record `name` fields with your domain, make sure to only insert `cloudflare-verify` as the record name. Otherwise, it may result in an incorrect record name, such as `cloudflare-verify.example.com.example.com`.

The verification record must remain in place for as long as your domain is active on a CNAME setup on Cloudflare.

## 3\. Update your nameservers

Update the nameservers at your domain registrar to point to your new authoritative DNS provider. Make sure to remove the Cloudflare nameservers.

## 4\. Clean up DNS records on Cloudflare

In Cloudflare, remove all records that are not of type A, AAAA, or CNAME, and also remove any A, AAAA, or CNAME records for hostnames you do not want to proxy after the conversion. After this cleanup, only the A, AAAA, or CNAME records for hostnames you want to proxy should remain in Cloudflare, and those same hostnames should have CNAME records pointing to `{your-hostname}.cdn.cloudflare.net` at your new authoritative DNS provider.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/conversions/","name":"DNS setup conversions"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/conversions/convert-full-to-partial/","name":"Convert full setup to partial setup"}}]}
```

---

---
title: Convert full setup to secondary setup
description: If you initially configured a full setup you can later convert your zone to use incoming zone transfers (Cloudflare as secondary).
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Convert full setup to secondary setup

If you initially configured a [primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/), you can later convert your zone to use [incoming zone transfers (Cloudflare as secondary)](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/).

Subdomain setup

If you also use subdomain setup[1](#user-content-fn-1), consider the [available combinations](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/setup/#available-setups) and whether your zone conversion could have any implications.

## Footnotes

1. Meaning you have one or more subdomains (`sub.example.com`) added to Cloudflare as their own zone, separate from your apex domain (`example.com`). [↩](#user-content-fnref-1)

Follow the steps below to achieve this conversion.

## 1\. Prepare DNS records

1. [Export a zone file](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/#export-records).
2. Import the zone file into your new primary DNS provider.
3. At your Cloudflare zone, use the [Update DNS Settings](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/methods/edit/) endpoint to enable [secondary DNS overrides](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/proxy-traffic/). Set the value for `secondary_overrides` to `true`.  
Note  
Enabling secondary DNS overrides is necessary in case you have DNS records that you wish to keep [proxied](https://developers.cloudflare.com/dns/proxy-status/).

## 2\. Prepare the zone transfers

1. Make adjustments to DNSSEC according to your option for [DNSSEC with secondary setup](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/dnssec-for-secondary/).
2. (Optional) Create a Transaction Signature (TSIG).  
A Transaction Signature (TSIG) authenticates communication between a primary and secondary DNS server.  
Note  
The TSIG names configured at your primary and secondary DNS providers have to be exactly the same. Any differences in TSIG names will cause zone transfers to fail.  
While optional, this step is highly recommended.  
   * [ Dashboard ](#tab-panel-7983)  
   * [ API ](#tab-panel-7984)  
To create a TSIG using the dashboard:  
   1. In the Cloudflare dashboard, go to the account **Settings** page.  
   [ Go to **Configurations** ](https://dash.cloudflare.com/?to=/:account/configurations)  
   2. Go to **DNS Settings**.  
   3. Under **DNS Zone Transfers**, for **TSIG**, select **Create**.  
   4. Enter the following information:  
         * **TSIG name**: The name of the TSIG object using domain name syntax (more details in [RFC 8945 section 4.2 ↗](https://datatracker.ietf.org/doc/html/rfc8945#section-4.2)).  
         * **Secret (optional)**: Get a shared secret to add to your third-party nameservers. If left blank, this field generates a random secret.  
         * **Algorithm**: Choose a TSIG signing algorithm.  
   5. Select **Create**.  
To create a TSIG using the API, send a [POST](https://developers.cloudflare.com/api/resources/dns/subresources/zone%5Ftransfers/subresources/tsigs/methods/create/) request.
3. Create a peer server.  
   * [ Dashboard ](#tab-panel-7981)  
   * [ API ](#tab-panel-7982)  
To create a peer server using the dashboard:  
   1. In the Cloudflare dashboard, go to the account **Settings** page.  
   [ Go to **Configurations** ](https://dash.cloudflare.com/?to=/:account/configurations)  
   2. Go to **DNS Settings**.  
   3. Under **DNS Zone Transfers**, for **Peer DNS servers**, select **Create**.  
   4. Enter the following information, paying particular attention to:  
         * **IP**: Specifies where Cloudflare sends transfer requests to.  
         * **Port**: Specifies the IP Port for the transfer IP.  
         * **Enable incremental (IXFR) zone transfers**: Specifies if Cloudflare sends IXFR requests in addition to the default AXFR requests.  
         * **Link an existing TSIG**: If desired, link the TSIG you [previously created](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/#1-create-tsig-optional).  
   5. Select **Create**.  
To create a peer DNS server using the API, send a [POST request](https://developers.cloudflare.com/api/resources/dns/subresources/zone%5Ftransfers/subresources/peers/).

## 3\. Convert the zone and initiate zone transfers

1. Use the [Edit Zone endpoint](https://developers.cloudflare.com/api/resources/zones/methods/edit/) with `type` set to `secondary` to convert the zone type. The existing records will remain in place.
2. In the Cloudflare dashboard, go to the **DNS Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings)
3. Select **Manage linked peers** under **DNS Zone Transfers**.
4. Link the peer server you created in the previous steps and select **Save**.
5. Back on the [**DNS Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings) page, select **Initiate zone transfer**.
6. Confirm the DNS records are transferring as expected.
7. Go to the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page and take note of your new **Cloudflare Nameservers**.
8. At your domain registrar (or parent zone), [update your nameservers](https://developers.cloudflare.com/dns/nameservers/update-nameservers/) to include the `secondary.cloudflare.com` nameservers.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/conversions/","name":"DNS setup conversions"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/conversions/convert-full-to-secondary/","name":"Convert full setup to secondary setup"}}]}
```

---

---
title: Convert partial setup to full setup
description: If you initially set up a partial domain on Cloudflare, you can later migrate it to a full setup.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Convert partial setup to full setup

If you initially set up a partial domain on Cloudflare, you can later migrate it to a [primary setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/) (also know as full setup).

Subdomain setup

If you also use subdomain setup[1](#user-content-fn-1), consider the [available combinations](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/setup/#available-setups) and whether your zone conversion could have any implications.

## Footnotes

1. Meaning you have one or more subdomains (`sub.example.com`) added to Cloudflare as their own zone, separate from your apex domain (`example.com`). [↩](#user-content-fnref-1)

## 1\. Prepare Cloudflare SSL/TLS

In the Cloudflare dashboard, either order an [advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/) or [upload a custom SSL certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/) for your website or application.

You should also verify that the [status](https://developers.cloudflare.com/ssl/reference/certificate-statuses/) of your SSL certificate is **Active**.

Note

It is possible to use [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) instead, but you should consider the following:

* Universal certificates can take at least [15 minutes](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/enable-universal-ssl/#full-dns-setup) to be issued.
* You should make sure to add Cloudflare nameservers to your registrar within 72 hours of the conversion process.
* Universal SSL only supports first-level subdomains. You can use [Advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) with the [Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/) option to automatically issue certificates for any proxied hostname.
* To minimize downtime, it is recommended having a certificate in place beforehand.

## 2\. Update settings in authoritative DNS

At least 24 hours prior to converting your zone, disable DNSSEC at your authoritative DNS provider.

Note

As a best practice, you should also delete the previous [zone activation TXT record](https://developers.cloudflare.com/dns/zone-setups/partial-setup/setup/#1-convert-your-zone-and-review-dns-records) at your authoritative DNS provider. To locate this value in the Cloudflare dashboard, go to the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page and find the **Verification TXT Record**.

## 3\. Convert to full setup

In the Cloudflare dashboard:

1. In the Cloudflare dashboard, select your partial zone (CNAME setup) and go to the **DNS Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings)
2. Select **Convert to Primary DNS** (this will not affect how your traffic is proxied).
3. Import your records into Cloudflare DNS and verify that they have been configured correctly. Usually, you will want to import [unproxied records](https://developers.cloudflare.com/dns/proxy-status/).

## 4\. Activate full setup

Get your assigned Cloudflare nameservers from the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page and [update your nameservers](https://developers.cloudflare.com/dns/nameservers/update-nameservers/) at your registrar.

Warning

If you are counting on Universal SSL certificates to cover your website or application, make sure to add Cloudflare nameservers to your registrar within 72 hours of the conversion process.

Cloudflare recommends that you also [enable DNSSEC](https://developers.cloudflare.com/dns/dnssec/) from the [**DNS Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings) page and add the DS record to your registrar.

Once all the DNS TTLs expire, all your DNS queries will be answered by the Cloudflare global network.

Start proxying additional hostnames by enabling the [proxy status](https://developers.cloudflare.com/dns/proxy-status/) (also known as orange-clouding) for specific DNS records. Previously proxied subdomains will continue to be proxied without any interruption.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/conversions/","name":"DNS setup conversions"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/conversions/convert-partial-to-full/","name":"Convert partial setup to full setup"}}]}
```

---

---
title: Convert partial setup to secondary setup
description: If you initially set up a partial zone on Cloudflare, you can later convert it to use a secondary setup.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Convert partial setup to secondary setup

If you initially set up a [partial zone (CNAME setup)](https://developers.cloudflare.com/dns/zone-setups/partial-setup/) on Cloudflare, you can later convert it to use a [secondary setup](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/).

Subdomain setup

If you also use subdomain setup[1](#user-content-fn-1), consider the [available combinations](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/setup/#available-setups) and whether your zone conversion could have any implications.

## Footnotes

1. Meaning you have one or more subdomains (`sub.example.com`) added to Cloudflare as their own zone, separate from your apex domain (`example.com`). [↩](#user-content-fnref-1)

This page will guide you through this conversion using [export and import](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/) and API calls.

## Before you begin

Make sure you consider the following:

* Proxying traffic with secondary zones requires a setting that is not turned on by default. Refer to [Secondary DNS override](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/proxy-traffic/) to learn more. The steps below include enabling this setting.
* There are a few options for [DNSSEC with incoming zone transfers](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/dnssec-for-secondary/). If you want to use DNSSEC, plan for which option you will configure and confirm that your other DNS provider(s) support the setup.
* You can prepare SSL/TLS in advance by either ordering an [advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/) or [uploading a custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/). You should confirm that the certificate covers all your proxied hostnames and that the [status of your SSL certificate ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) is **Active**.

## 1\. Prepare a zone file

1. Export a zone file from the authoritative DNS provider you were using with your CNAME setup (partial).
2. Edit the zone file to remove any occurrences of the `cdn.cloudflare.net` suffix.
* If the `CNAME` target is only appending the Cloudflare suffix to the same hostname at which it is created, replace it by the records on the Cloudflare partial zone.

Example

Original record in authoritative DNS provider:

| Type  | Name            | Content                            |
| ----- | --------------- | ---------------------------------- |
| CNAME | www.example.com | www.example.com.cdn.cloudflare.net |

Records in the Cloudflare partial zone:

| Type | Name            | Content |
| ---- | --------------- | ------- |
| A    | www.example.com | <IPv4>  |
| A    | www.example.com | <IPv4>  |

Final records adjusted in the zone file:

| Type | Name            | Content |
| ---- | --------------- | ------- |
| A    | www.example.com | <IPv4>  |
| A    | www.example.com | <IPv4>  |

* If the `CNAME` record points to a different hostname, keep this record but remove the `cdn.cloudflare.net` suffix, and also bring the records from the Cloudflare partial zone.

Example

Original record in authoritative DNS provider:

| Type  | Name            | Content                                       |
| ----- | --------------- | --------------------------------------------- |
| CNAME | www.example.com | other-hostname.example.com.cdn.cloudflare.net |

Records in the Cloudflare partial zone (CNAME setup):

| Type | Name                       | Content |
| ---- | -------------------------- | ------- |
| A    | other-hostname.example.com | <IPv4>  |
| A    | other-hostname.example.com | <IPv4>  |

Final records adjusted in the zone file:

| Type  | Name                       | Content                    |
| ----- | -------------------------- | -------------------------- |
| CNAME | www.example.com            | other-hostname.example.com |
| A     | other-hostname.example.com | <IPv4>                     |
| A     | other-hostname.example.com | <IPv4>                     |

## 2\. Configure the Cloudflare zone

1. Use the [Import DNS Records endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/import/) with a properly [formatted zone file](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/#format-your-zone-file) to import the records into your partial zone.  
The zone file size limit is 256 KiB (262144 bytes).  
 Existing and already proxied records will not be overwritten by the import.
2. Use the [Update DNS Settings endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/methods/edit/) with `secondary_overrides` set to `true`, to enable Secondary DNS Override.

Warning

This step is essential so that Cloudflare can keep the proxy status of the records after the conversion.

1. Use the [Edit Zone endpoint](https://developers.cloudflare.com/api/resources/zones/methods/edit/) with `type` set to `secondary`, to convert the zone type.  
You can verify if it answers as expected by querying the new assigned secondary nameservers. You can find your nameservers on the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page, and they should follow a format like `ns0123.secondary.cloudflare.com`.

Terminal window

```

# Replace ns0123 with your actual Cloudflare nameservers

dig example.com @ns0123.secondary.cloudflare.com


```

1. At your registrar, [update your nameservers](https://developers.cloudflare.com/dns/nameservers/update-nameservers/) to point to the Cloudflare nameservers.

Once the time to live (TTL) of previous `NS` records is expired and this information is evicted from resolvers' cache, your zone will be properly delegated to Cloudflare. In order to update DNS records, you must configure [zone transfers](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/) in the next steps.

## 3\. Configure the zone transfers

1. Remove all references to `cdn.cloudflare.net` from your primary DNS provider. You can do this by importing the same zone file you prepared in [Step 1](#1-prepare-a-zone-file) onto your primary zone.

Warning

If you keep any DNS records that still refer `cdn.cloudflare.net`, HTTP traffic for the respective hostnames will break.

1. Enable outgoing zone transfers at your primary provider and create a peer DNS server on your Cloudflare account.

* [ Dashboard ](#tab-panel-7987)
* [ API ](#tab-panel-7988)

To create a peer server using the dashboard:

1. In the Cloudflare dashboard, go to the account **Settings** page.  
[ Go to **Configurations** ](https://dash.cloudflare.com/?to=/:account/configurations)
2. Go to **DNS Settings**.
3. Under **DNS Zone Transfers**, for **Peer DNS servers**, select **Create**.
4. Enter the following information, paying particular attention to:  
   * **IP**: Specifies where Cloudflare sends transfer requests to.  
   * **Port**: Specifies the IP Port for the transfer IP.  
   * **Enable incremental (IXFR) zone transfers**: Specifies if Cloudflare sends IXFR requests in addition to the default AXFR requests.  
   * **Link an existing TSIG**: If desired, link the TSIG you [previously created](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/#1-create-tsig-optional).
5. Select **Create**.

To create a peer DNS server using the API, send a [POST request](https://developers.cloudflare.com/api/resources/dns/subresources/zone%5Ftransfers/subresources/peers/).

1. Link your Cloudflare zone to the peer DNS server you just created.

* [ Dashboard ](#tab-panel-7985)
* [ API ](#tab-panel-7986)

1. In the Cloudflare dashboard, go to the **DNS Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings)
2. Under **DNS Zone Transfers**, select **Manage linked peers**.
3. Choose a value for **Zone refresh**, which controls the number of seconds between zone updates from your primary DNS server.  
Warning  
Cloudflare will not use the REFRESH value inside the SOA record that is served by your primary provider. Instead the value of zone refresh configured for your secondary zone on Cloudflare will be used to determine the interval after which the SOA serial of the primary zone will be checked for changes.
4. Select the peer server you previously created. If needed, you can link more than one peer server to a zone.
5. Select **Save** to confirm.

Use the [Update Secondary Zone Configuration endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/zone%5Ftransfers/subresources/peers/methods/update/) to link your Cloudflare zone to the peer DNS server.

1. On the [**DNS Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings) page, confirm the linked peer is listed under **DNS Zone Transfers**, and select **Initiate zone transfer**. Alternatively, you can use the [Force AXFR endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/zone%5Ftransfers/subresources/force%5Faxfr/methods/create/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/conversions/","name":"DNS setup conversions"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/conversions/convert-partial-to-secondary/","name":"Convert partial setup to secondary setup"}}]}
```

---

---
title: Convert secondary setup to full setup
description: If you initially set up incoming zone transfers (Cloudflare as secondary), you can later convert your zone to use a full setup.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Convert secondary setup to full setup

If you initially set up [incoming zone transfers (Cloudflare as secondary)](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/), you can later convert your zone to use a [primary setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/) (also know as full setup).

Subdomain setup

If you also use subdomain setup[1](#user-content-fn-1), consider the [available combinations](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/setup/#available-setups) and whether your zone conversion could have any implications.

## Footnotes

1. Meaning you have one or more subdomains (`sub.example.com`) added to Cloudflare as their own zone, separate from your apex domain (`example.com`). [↩](#user-content-fnref-1)

Follow the steps below to achieve this conversion.

## 1\. Stop transferring the zone

1. In the Cloudflare dashboard, go to the **DNS Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings)
2. Under **DNS Zone Transfers**, and select **Manage linked peers**.
3. Unlink the peer and select **Save**.

At this point, your zone will be read-only.

## 2\. Prepare for the conversion

1. Plan for [DNSSEC settings](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/dnssec-for-secondary/). If you were previously using [Pre-signed DNSSEC](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/dnssec-for-secondary/#set-up-pre-signed-dnssec), consider disabling DNSSEC before starting the conversion.  
Warning  
Leaving Pre-signed DNSSEC enabled after converting to a full zone can prevent DNS records from propagating to Cloudflare's edge, causing your zone to return `REFUSED` responses. If you experience this after converting, verify by querying your assigned nameservers using [digwebinterface.com ↗](https://digwebinterface.com/), then check the [DNSSEC Details endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/get/) for `dnssec_presigned: true` and disable it using the [Edit DNSSEC Status endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/edit/) with `dnssec_presigned` set to `false`.
2. Make sure the [proxy statuses](https://developers.cloudflare.com/dns/proxy-status/) of your DNS records are consistently set:  
   * If you have [Secondary DNS override](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/proxy-traffic/), confirm each record has the appropriate setting (**Proxied** or **DNS only**).  
   * If [Secondary DNS override](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/proxy-traffic/) is disabled, make sure all of your DNS records are listed as **DNS only**.
3. (Optional) For consistency, use the [Update DNS Settings](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/methods/edit/) endpoint to specify SOA record fields according to your needs. Once Cloudflare automatically generates an SOA record for your zone on primary setup (full), the field overrides will be considered.

## 3\. Convert your zone

1. Use the [Edit Zone endpoint](https://developers.cloudflare.com/api/resources/zones/methods/edit/) with `type` set to `full` to convert the zone type. Existing DNS records will not be affected.
2. Go to the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page and take note of your new **Cloudflare Nameservers**.
3. At your domain registrar (or parent zone), [update your nameservers](https://developers.cloudflare.com/dns/nameservers/update-nameservers/). Replace the nameservers ending in `secondary.cloudflare.com` by the ones ending in `ns.cloudflare.com`.  
Note  
If Cloudflare will be your only primary DNS provider, remove any other nameservers as well.
4. Delete the previous SOA record to make sure Cloudflare generates a new one.
5. (Optional) If Cloudflare was previously not signing your records and you wish to use DNSSEC, follow the steps to [Enable DNSSEC](https://developers.cloudflare.com/dns/dnssec/#enable-dnssec).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/conversions/","name":"DNS setup conversions"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/conversions/convert-secondary-to-full/","name":"Convert secondary setup to full setup"}}]}
```

---

---
title: Convert secondary setup to partial setup
description: If you initially set up incoming zone transfers (Cloudflare as secondary), you can later convert your zone to use a partial setup.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Convert secondary setup to partial setup

If you initially set up [incoming zone transfers (Cloudflare as secondary)](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/), you can later convert your zone to use a CNAME setup (partial).

Subdomain setup

If you also use subdomain setup[1](#user-content-fn-1), consider the [available combinations](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/setup/#available-setups) and whether your zone conversion could have any implications.

## Footnotes

1. Meaning you have one or more subdomains (`sub.example.com`) added to Cloudflare as their own zone, separate from your apex domain (`example.com`). [↩](#user-content-fnref-1)

Follow the steps below to achieve this conversion.

## 1\. Stop transferring the zone

1. In the Cloudflare dashboard, go to the **DNS Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings)
2. Under **DNS Zone Transfers**, and select **Manage linked peers**.
3. Unlink the peer and select **Save**.

At this point, your zone will be read-only.

## 2\. Configure your authoritative DNS provider

1. (Optional) If you are also migrating to a new authoritative DNS provider, export a zone file from the previous provider and import it into the new one.
2. At your authoritative DNS provider, create `CNAME` records pointing to `{your-hostname}.cdn.cloudflare.net` for every hostname you wish to proxy through Cloudflare.  
Example CNAME record at authoritative DNS provider  
The `CNAME` record for `www.example.com` would be:  
```  
www.example.com CNAME www.example.com.cdn.cloudflare.net  
```
3. At your authoritative DNS provider, remove any previously existing `A`, `AAAA`, or `CNAME` records referencing the hostnames you want to proxy through Cloudflare. For these hostnames, leave only the records pointing to `{your-hostname}.cdn.cloudflare.net`.

## 3\. Convert your Cloudflare zone

1. Back at your Cloudflare zone, confirm that you have all the `A`, `AAAA`, or `CNAME` [DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) needed for the hostnames you pointed to `{your-hostname}.cdn.cloudflare.net` in the previous step. You can also delete any DNS records that have a different type, as they will no longer resolve once you convert your zone to a CNAME setup (partial).
2. Use the [Edit Zone endpoint](https://developers.cloudflare.com/api/resources/zones/methods/edit/) with `type` set to `partial` to convert the zone type. Existing DNS records will not be affected.
3. On the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page, get the **Verification TXT Record** and add it at your authoritative DNS provider.  
Example verification record  
A verification record for `sub.example.com` might be:  
| Type | Name                              | Content             |  
| ---- | --------------------------------- | ------------------- |  
| TXT  | cloudflare-verify.sub.example.com | 966215192-518620144 |  
If your authoritative DNS provider automatically appends DNS record `name` fields with your domain, make sure to only insert `cloudflare-verify` as the record name. Otherwise, it may result in an incorrect record name, such as `cloudflare-verify.sub.example.com.sub.example.com`.  
After creating the record, you can use this [Dig Web Interface link ↗](https://digwebinterface.com/?type=TXT&ns=auth&nameservers=) to search (`dig`) for `cloudflare-verify.<YOUR DOMAIN>` and validate if it is working.  
Note  
The verification record must remain in place for as long as you want your CNAME setup (partial) to be active on Cloudflare.

## 4\. Update nameservers

At your domain registrar (or parent zone), [update the nameservers](https://developers.cloudflare.com/dns/nameservers/update-nameservers/). In a CNAME setup (partial), only the nameservers of your external DNS provider should be listed.

* Remove any `secondary.cloudflare.com` nameservers if you used to have them.
* If you are also migrating to a new authoritative DNS provider, add your new nameservers.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/conversions/","name":"DNS setup conversions"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/conversions/convert-secondary-to-partial/","name":"Convert secondary setup to partial setup"}}]}
```

---

---
title: Primary setup (Full)
description: Use Cloudflare as your primary DNS provider.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Primary setup (Full)

Cloudflare DNS offers a few different [setup options](https://developers.cloudflare.com/dns/zone-setups/). A primary setup (also known as full) is the most common and the only one available for Free or Pro plans.

In a primary setup, Cloudflare is your primary authoritative DNS provider, which means that, when a visitor tries to access your website or application, DNS resolvers will consider the [DNS records](https://developers.cloudflare.com/dns/manage-dns-records/) that you have on Cloudflare.

For this to work, you must go through a few steps that involve not only Cloudflare, but also your registrar and your previous DNS provider (if you were using one). Refer to [Set up a primary zone](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/) for detailed instructions.

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/full-setup/","name":"Primary setup (Full)"}}]}
```

---

---
title: Set up a primary zone (Full setup)
description: If you want to use Cloudflare as your primary DNS provider and manage your DNS records, your domain should be using a full setup.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Set up a primary zone (Full setup)

Cloudflare DNS offers a few different [setup options](https://developers.cloudflare.com/dns/zone-setups/). A primary setup (also known as full) is the most common and the only one available for Free or Pro plans. For details, refer to [About](https://developers.cloudflare.com/dns/zone-setups/full-setup/). For more introductory context, refer to [Concepts](https://developers.cloudflare.com/dns/concepts/).

## Before you begin

Make sure that you:

* Create a Cloudflare account — If you have not already, [sign up for a Cloudflare account](https://developers.cloudflare.com/fundamentals/account/create-account/).
* Own a domain name — You need a registered domain (for example, `example.com`). If you do not have one, you can [register a domain at-cost through Cloudflare Registrar ↗](https://dash.cloudflare.com/?to=/:account/domains/register). Domains purchased through Cloudflare Registrar automatically use Cloudflare for authoritative DNS, so you can skip the rest of this tutorial.

## 1\. Add your domain to Cloudflare

* [ Dashboard ](#tab-panel-7991)
* [ API ](#tab-panel-7992)

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com).  
[ Go to **Domains** ](https://dash.cloudflare.com/?to=/:account/domains/overview)
2. Select **Onboard a domain**.
3. Enter your apex domain (for example, `example.com`) and choose how you would like to add your DNS records.
4. Select **Continue** and choose a [plan ↗](https://www.cloudflare.com/plans/#compare-features).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Zone Edit`
* `Zone DNS Edit`

Create Zone

```

curl "https://api.cloudflare.com/client/v4/zones" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "name": "<YOUR_DOMAIN>",

    "account": {

        "id": "<YOUR_ACCOUNT_ID>"

    }

  }'


```

Note

If Cloudflare is unable to identify your domain as a registered domain, make sure you are using an existing [top-level domain ↗](https://www.cloudflare.com/learning/dns/top-level-domain/) (`.com`, `.net`, `.biz`, or others).

Cloudflare requires your apex domain to be one level below a valid TLD defined in the [Public Suffix List (PSL) ↗](https://github.com/publicsuffix/list/blob/master/public%5Fsuffix%5Flist.dat). Enterprise customers can onboard lower-level subdomains using [Subdomain setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/).

DNS records quick scan

Cloudflare can [automatically scan for your records](https://developers.cloudflare.com/dns/zone-setups/reference/dns-quick-scan/) and add them to the [DNS zone](https://developers.cloudflare.com/dns/concepts/#zone) for you, or you can add records manually. These records show up under your domain on the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page of the dashboard.

Note

If you add a zone via the [API](https://developers.cloudflare.com/api/resources/zones/methods/create/), you can manually invoke the quick scan with the [Trigger DNS Records Scan endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/scan%5Ftrigger/).

## 2\. Review your DNS records

Your DNS records must be accurate for your domain to work properly. If you don't know what DNS records are, consider the video below for a quick explanation.

Note

If you activate your domain on Cloudflare _without_ setting up the correct DNS records for your domain, your visitors may experience [DNS\_PROBE\_FINISHED\_NXDOMAIN](https://developers.cloudflare.com/dns/troubleshooting/dns-probe-finished-nxdomain/) errors.

### Common records

Since the quick scan is not guaranteed to find all existing DNS records, you need to review your records, paying special attention to the following:

* [Zone apex records (example.com)](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-zone-apex/)  
More about zone apex records  
Zone apex refers to the domain or subdomain that you are [adding to Cloudflare](https://developers.cloudflare.com/dns/concepts/#zone).  
Usually, the zone apex record makes your domain accessible by visitors. In this case, the necessary record type ([A, AAAA, or CNAME](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#ip-address-resolution)) and its content will depend on the provider that [hosts](https://developers.cloudflare.com/fundamentals/manage-domains/#host-your-domain) your website or application.  
If you are using Cloudflare Workers, refer to [Custom domains](https://developers.cloudflare.com/workers/configuration/routing/custom-domains/).  
If you are using other providers, look for their guidance on how to connect domains managed on external DNS services. Then, make sure you have the records required by your hosting provider on your [DNS records table](https://developers.cloudflare.com/dns/manage-dns-records/#dns-records-table) at Cloudflare.
* [Subdomain records (www.example.com or blog.example.com)](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-subdomain/)  
More about subdomain records  
Most subdomains serve a specific purpose within the overall context of your website. For example, `blog.example.com` might be your blog, `support.example.com` could be your customer help portal, and `store.example.com` would be your e-commerce site.  
Even if you do not require specific subdomains, you might want to set up at least a subdomain record on `www`. It will usually point to the same content as what you have on the apex domain (`example.com`) or use a [redirect](https://developers.cloudflare.com/fundamentals/manage-domains/manage-subdomains/#redirect-a-subdomain-to-the-apex-domain). Having a subdomain DNS record on `www` helps guarantee that a visitor who types `www.` in front of your domain address can still find your website or application.
* [Email records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/email-records/)  
More about email records  
Depending on your business needs, you can configure DNS records so that you can use your domain to receive emails, receive and send emails from your domain, or prevent others from sending emails on your behalf (spoofing).  
Below are some examples of what those DNS records might look like. The exact values for your DNS mail records depend on your email provider. If you have issues, review the [Troubleshooting](https://developers.cloudflare.com/dns/troubleshooting/email-issues/) and contact your email service provider to confirm your DNS records are correct.  
| Type | Name           | Content                       | Proxy status | TTL  |  
| ---- | -------------- | ----------------------------- | ------------ | ---- |  
| A    | mail           | 192.0.2.1                     | DNS Only     | Auto |  
| MX   | example.com    | 5 john.mx.example-server.test | DNS Only     | Auto |  
| TXT  | \_dmarc        | "v=DMARC1; p=reject; sp=...   | DNS Only     | Auto |  
| TXT  | \*.\_domainkey | "v=DKIM1; k=rsa; p=..."       | DNS Only     | Auto |  
| TXT  | example.com    | "v=spf1 ip4:..."              | DNS Only     | Auto |

### Proxy status

Each A, AAAA, and CNAME record has a [proxy status](https://developers.cloudflare.com/dns/proxy-status/) toggle:

* **Proxied** (orange cloud): web traffic goes through the Cloudflare network, which provides caching, DDoS protection, and other security features.
* **DNS only** (gray cloud): Cloudflare returns the DNS record value but does not proxy traffic. Use this for CNAME records that verify your domain for third-party services.

## 3\. Change your nameservers

Your domain will be assigned two authoritative Cloudflare nameservers. Nameservers are specialized servers that store your domain's DNS records and "answer" requests from browsers by providing the specific IP address needed to connect to your website.

Warning

If your domain is particularly sensitive to downtime, review our suggestions to [minimize downtime](https://developers.cloudflare.com/fundamentals/performance/minimize-downtime/).

### 3.1\. Get nameserver names

* [ Dashboard ](#tab-panel-7989)
* [ API ](#tab-panel-7990)

Your assigned nameservers are displayed as part of the onboarding flow. If you need to find them once again, go the zone **Overview** page.

[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/) 

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Trust and Safety Write`
* `Trust and Safety Read`
* `Zero Trust: PII Read`
* `Zaraz Edit`
* `Zaraz Read`
* `Zaraz Admin`
* `Access: Apps and Policies Revoke`
* `Access: Apps and Policies Write`
* `Access: Apps and Policies Read`
* `Access: Apps and Policies Revoke`
* `Access: Mutual TLS Certificates Write`
* `Access: Organizations, Identity Providers, and Groups Write`
* `Zone Settings Write`
* `Zone Settings Read`
* `Zone Read`
* `DNS Read`
* `Workers Scripts Write`
* `Workers Scripts Read`
* `Zone Write`
* `Workers Routes Write`
* `Workers Routes Read`
* `Stream Write`
* `Stream Read`
* `SSL and Certificates Write`
* `SSL and Certificates Read`
* `Logs Write`
* `Logs Read`
* `Cache Purge`
* `Page Rules Write`
* `Page Rules Read`
* `Load Balancers Write`
* `Load Balancers Read`
* `Firewall Services Write`
* `Firewall Services Read`
* `DNS Write`
* `Apps Write`
* `Analytics Read`
* `Access: Apps and Policies Write`
* `Access: Apps and Policies Read`

Zone Details

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

Note

Cloudflare automatically assigns nameservers to a domain and these assignments cannot be changed. For more details, refer to [Nameserver assignments](https://developers.cloudflare.com/dns/nameservers/nameserver-options/#assignment-method).

### 3.2\. Log in to your registrar

Log in to the admin account for your domain registrar. If you do not know your provider, use [ICANN Lookup ↗](https://lookup.icann.org/).

Note

Depending on your use case, you may have to perform this step on the DNS records management of your domain parent zone, or at a domain reseller, instead. Refer to [Nameservers](https://developers.cloudflare.com/dns/nameservers/update-nameservers/#specific-processes) for details.

### 3.3\. Turn off DNSSEC

If your domain has [DNSSEC](https://developers.cloudflare.com/dns/dnssec/)[1](#user-content-fn-1) active, you must [turn it off](https://developers.cloudflare.com/dns/dnssec/#disable-dnssec) at your registrar before replacing nameservers. Changing nameservers while DNSSEC is active can cause your domain to become unreachable. You can [re-enable DNSSEC through Cloudflare](https://developers.cloudflare.com/dns/dnssec/#enable-dnssec) after your domain is active.

Provider-specific DNSSEC instructions

This is not an exhaustive list, but the following links may be helpful:

* [DNSimple ↗](https://support.dnsimple.com/articles/cloudflare-ds-record/)
* [Domaindiscount24 ↗](https://support.domaindiscount24.com/hc/articles/4409759478161)
* [DreamHost ↗](https://help.dreamhost.com/hc/en-us/articles/219539467)
* [Dynadot ↗](https://www.dynadot.com/help/question/set-DNSSEC)
* [Enom ↗](https://support.enom.com/support/solutions/articles/201000065386)
* [Gandi ↗](https://docs.gandi.net/en/domain%5Fnames/advanced%5Fusers/dnssec.html)
* [GoDaddy ↗](https://www.godaddy.com/help/add-a-ds-record-23865)
* [Hostinger ↗](https://www.hostinger.com/support/3667267-how-to-use-dnssec-records-at-hostinger/)
* [Hover ↗](https://support.hover.com/support/solutions/articles/201000064716)
* [Infomaniak ↗](https://faq.infomaniak.com/2187)
* [InMotion Hosting ↗](https://www.inmotionhosting.com/support/edu/cpanel/enable-dnssec-cloudflare/)
* [INWX ↗](https://kb.inwx.com/en-us/3-nameserver/131)
* [Joker.com ↗](https://joker.com/faq/books/jokercom-faq-en/page/dnssec)
* [Name.com ↗](https://www.name.com/support/articles/205439058-managing-dnssec)
* [Namecheap ↗](https://www.namecheap.com/support/knowledgebase/article.aspx/9722/2232/managing-dnssec-for-domains-pointed-to-custom-dns/)
* [NameISP ↗](https://support.nameisp.com/knowledgebase/dns)
* [Namesilo ↗](https://www.namesilo.com/support/v2/articles/domain-manager/ds-records)
* [OVH ↗](https://help.ovhcloud.com/csm/en-dns-secure-domain-dnssec?id=kb%5Farticle%5Fview&sysparm%5Farticle=KB0051637)
* [Squarespace ↗](https://support.squarespace.com/hc/articles/4404183898125-Nameservers-and-DNSSEC-for-Squarespace-managed-domains#toc-dnssec)
* [Registro.br ↗](https://registro.br/tecnologia/dnssec/?secao=tutoriais-dns)
* [Porkbun ↗](https://kb.porkbun.com/article/93-how-to-install-dnssec) (do not fill out **keyData**)
* [TransIP ↗](https://www.transip.eu/knowledgebase/150-secure-domains-custom-nameservers-dnssec/)

Note

If your previous provider allows you to add DNSKEY records on the zone apex and use these records in responses to DNS queries, refer to this [migration tutorial](https://developers.cloudflare.com/dns/dnssec/dnssec-active-migration/) to learn how to migrate a zone with DNSSEC enabled.

### 3.4\. Update your registrar

1. Remove your existing authoritative nameservers.
2. Add the nameservers provided by Cloudflare. If their names are not **copied exactly**, your DNS will not resolve correctly.

Provider-specific instructions

This is not an exhaustive list of provider-specific instructions, but the following links may be helpful:

* [Ionos ↗](https://www.ionos.com/help/domains/using-your-own-name-servers/using-your-own-name-servers-for-a-domain/)
* [101Domain ↗](https://help.101domain.com/kb/managing-name-server-records)
* [Amazon ↗](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-name-servers-glue-records.html#domain-name-servers-glue-records-adding-changing)
* [Blacknight ↗](https://help.blacknight.com/hc/articles/4413036322321-How-do-I-change-the-nameservers-for-my-domain)
* [BlueHost ↗](https://www.bluehost.com/help/article/custom-nameservers)
* [DirectNIC ↗](https://directnic.com/knowledge/article/33:how%2Bdo%2Bi%2Bmodify%2Bname%2Bservers%2Bfor%2Bmy%2Bdomain%2Bname%253F)
* [DNSMadeEasy ↗](http://www.dnsmadeeasy.com/support/faq/)
* [Domain.com ↗](https://www.domain.com/help/article/domain-management-how-to-update-nameservers)
* [Dotster ↗](https://www.dotster.com/help/article/domain-management-how-to-update-nameservers)
* [DreamHost ↗](https://help.dreamhost.com/hc/en-us/articles/360038897151)
* [EasyDNS ↗](https://kb.easydns.com/knowledge/settingchanging-nameservers/)
* [Enom ↗](https://help.enom.com/hc/en-us/articles/115000486451-Nameservers-NS)
* [Fast Domain ↗](https://www.fastdomain.com/hosting/help/transfer%5Fclient%5Fstart)
* [FlokiNET ↗](https://billing.flokinet.is/index.php?rp=/knowledgebase/57/Nameserver-and-DNS-records.html)
* [Gandi ↗](https://docs.gandi.net/en/domain%5Fnames/common%5Foperations/changing%5Fnameservers.html)
* [GoDaddy ↗](https://www.godaddy.com/help/change-nameservers-for-your-domain-names-664)
* [HostGator ↗](https://www.hostgator.com/help/article/changing-name-servers)
* [Hostico ↗](https://hostico.ro/docs/setarea-nameserverelor-din-contul-de-client-hostico/)
* [HostMonster ↗](https://my.hostmonster.com/cgi/help/222)
* [Hover ↗](https://support.hover.com/support/solutions/articles/201000064742-changing-your-domain-nameservers)
* [Internetdbs ↗](https://faq.internetbs.net/hc/en-gb/articles/4516921367837-How-to-update-Nameservers-for-a-domain)
* [iPage ↗](https://www.ipage.com/help/article/domain-management-how-to-update-nameservers)
* [MelbourneIT ↗](https://support.melbourneit.au/docs/how-do-i-manage-my-dns-on-cpanel)
* [Moniker ↗](https://support.moniker.com/hc/en-gb/articles/10101271418653-How-to-update-Nameservers-for-a-domain)
* [Name.com ↗](https://www.name.com/support/articles/205934457-registering-custom-nameservers)
* [Namecheap ↗](https://www.namecheap.com/support/knowledgebase/article.aspx/767/10/how-can-i-change-the-nameservers-for-my-domain)
* [Network Solutions ↗](https://www.networksolutions.com/manage-it/edit-nameservers.jsp)
* [OVH ↗](https://docs.ovh.com/gb/en/domains/web%5Fhosting%5Fgeneral%5Finformation%5Fabout%5Fdns%5Fservers/#step-2-edit-your-domains-dns-servers)
* [Porkbun ↗](https://kb.porkbun.com/article/22-how-to-change-your-nameservers)
* [Rackspace ↗](https://support.rackspace.com/how-to/rackspace-name-servers/)
* [Register ↗](https://www.register.com/knowledge)
* [Squarespace ↗](https://support.squarespace.com/hc/articles/4404183898125-Nameservers-and-DNSSEC-for-Squarespace-managed-domains#toc-open-the-domain-s-advanced-settings)
* [Site5 ↗](https://kb.site5.com/dns-2/custom-nameservers/)
* [Softlayer ↗](https://cloud.ibm.com/docs/dns?topic=dns-add-edit-or-delete-custom-name-servers-for-a-domain)
* [Yola ↗](https://helpcenter.yola.com/hc/articles/360012492660-Changing-your-name-servers)

To avoid common issues, refer to our [Nameserver replacement checklist](https://developers.cloudflare.com/dns/zone-setups/full-setup/troubleshooting/).

### 3.5\. Verify changes

Wait up to 24 hours while your registrar updates your nameservers.

When your domain is **Active**:

* You will receive an email from Cloudflare.
* Your domain will have a [status](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/) of **Active** on the **Domains** page of your account.
* Online tools such as [https://www.whatsmydns.net/ ↗](https://www.whatsmydns.net/) will show your Cloudflare-assigned nameservers (most of these tools use cached query results, so it may take longer for them to show the updated nameservers).
* CLI commands will show your Cloudflare-assigned nameservers

```

*macOS/Linux*


whois <DOMAIN_NAME>

dig ns <DOMAIN_NAME> @1.1.1.1

dig ns <DOMAIN_NAME> @8.8.8.8

dig <DOMAIN_NAME> +trace


*Windows*


nslookup -type=ns <DOMAIN_NAME> 1.1.1.1

nslookup -type=ns <DOMAIN_NAME> 8.8.8.8


```

Note

If you see unexpected results, refer to our [troubleshooting suggestions](https://developers.cloudflare.com/dns/zone-setups/full-setup/troubleshooting/) and check with your domain registrar.

## 4\. Re-enable DNSSEC

If you turned off DNSSEC before updating your nameservers, you can now [re-enable DNSSEC through Cloudflare](https://developers.cloudflare.com/dns/dnssec/) to protect your domain from spoofing.

## Footnotes

1. A security feature that protects DNS records from spoofing [↩](#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":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/full-setup/","name":"Primary setup (Full)"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/full-setup/setup/","name":"Set up a primary zone (Full setup)"}}]}
```

---

---
title: Troubleshooting
description: Learn how to troubleshoot issues with a primary setup (full)
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

If you see unexpected results when [changing your nameservers](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/), review the following troubleshooting questions.

## Is a DS record present at your registrar?

You need to remove any pre-Cloudflare **DS** records at your registrar to update your authoritative nameservers. This will disable DNSSEC and allow Cloudflare to resolve your domain name.

You can then [re-enable DNSSEC](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/#4-re-enable-dnssec) in Cloudflare and at your registrar after you have changed your nameservers.

## Do the nameservers at your registrar exactly match the values provided by Cloudflare?

If the nameservers in your registrar do not exactly match those provided by Cloudflare, your domain will not resolve correctly.

## Are additional nameservers listed at your registrar?

If so, you should remove these nameservers.

You should have only Cloudflare nameservers listed at your registrar.

## Have you waited longer than 24 hours?

For some registrars, you will need to wait up to 24 hours for updates to your nameservers.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/full-setup/","name":"Primary setup (Full)"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/full-setup/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: CNAME setup (Partial)
description: Use Cloudflare with your existing DNS provider via CNAME setup.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# CNAME setup (Partial)

A CNAME setup (also known as partial setup) allows you to use [Cloudflare's reverse proxy](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/) while maintaining your primary and authoritative DNS provider.

Use this option to proxy only individual subdomains through Cloudflare when you cannot change your authoritative DNS provider. You will be able to create A, AAAA, and CNAME records, which are the DNS record types that can be [proxied](https://developers.cloudflare.com/dns/proxy-status/).

Availability

A CNAME setup (partial) is only available to customers on a Business or Enterprise plan. Partial setups are not supported on Cloudflare Registrar domains.

Once you are on a CNAME setup (partial), the actual resolution of your records to Cloudflare depends on CNAME records [added at your authoritative DNS provider](https://developers.cloudflare.com/dns/zone-setups/partial-setup/setup/#3-add-dns-records). Check your authoritative DNS provider to know which records are pointing to `{your-hostname}.cdn.cloudflare.net`.

## How to

* [Set up a partial zone (CNAME setup)](https://developers.cloudflare.com/dns/zone-setups/partial-setup/setup/)
* [Convert a CNAME setup (partial) to a primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/conversions/convert-partial-to-full/)
* [Convert a CNAME setup (partial) to a secondary setup](https://developers.cloudflare.com/dns/zone-setups/conversions/convert-partial-to-secondary/)
* [Create DNS records of other types](https://developers.cloudflare.com/dns/zone-setups/partial-setup/setup/#other-record-types)

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | No  | No       | Yes        | Yes |

## Reference

### DNS resolution

When you have a partial zone ([CNAME setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)), Cloudflare resolves [DNS records differently](https://developers.cloudflare.com/dns/zone-setups/partial-setup/dns-resolution/) than for primary zones (full setup).

### CNAME flattening

A CNAME setup (partial) requires the proxied hostname to be pointed to Cloudflare via a CNAME record. Since [CNAME records are not allowed on the zone apex ↗](https://datatracker.ietf.org/doc/html/rfc1912#section-2.4) (`example.com`), you can only proxy your zone apex to Cloudflare if your authoritative DNS provider supports [CNAME Flattening ↗](https://blog.cloudflare.com/introducing-cname-flattening-rfc-compliant-cnames-at-a-domains-root/).

If your authoritative DNS provider does not support CNAME Flattening, redirect its traffic — for example, with an `.htaccess` file — to a subdomain proxied to Cloudflare. Alternatively, you can use [static IPs or BYOIPs](https://developers.cloudflare.com/fundamentals/concepts/cloudflare-ip-addresses/#customize-cloudflare-ip-addresses).

### DDoS protection

[DDoS protection](https://developers.cloudflare.com/ddos-protection/) for attacks against DNS infrastructure is only available for domains on [primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/). Domains on the CNAME setup (partial) are not using Cloudflare authoritative nameservers.

### Domain ownership

Enterprise customers can use [zone holds](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/) to prevent other teams in the organization from adding zones that are already active in another Cloudflare account. For CNAME setups (partial), if the same zone is added to different accounts, the last account to complete the setup will gain ownership.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/partial-setup/","name":"CNAME setup (Partial)"}}]}
```

---

---
title: DNS resolution
description: How DNS resolution works for partial CNAME setups.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNS resolution

When you have a partial zone ([CNAME setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)), Cloudflare handles DNS records a bit differently from primary zones (full setup) in order to internally resolve the origin server where proxied HTTP requests are sent to.

## Records within the same zone

When you [create a new DNS record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) in a partial zone, Cloudflare automatically checks whether any of your CNAME records point to existing A, AAAA, or CNAME records within the same zone.

For example, Cloudflare would show a warning if you had the following records in your partial zone:

```

sub1.partialzone.com   CNAME   sub2.partialzone.com

sub2.partialzone.com   A       192.0.2.1


```

Since Cloudflare contains both the CNAME and its target, our DNS resolution will send incoming HTTP requests to `sub1.partialzone.com` to the origin `192.0.2.1`.

This can cause issues if you already have DNS records for `sub2.partialzone.com` at your authoritative DNS provider. These records may point to `192.0.2.4`, another IP address, or another domain but - because Cloudflare contains the initial record and the target - it never queries your authoritative DNS provider for the record for `sub2.partialzone.com`.

    flowchart TD
      accTitle: DNS resolution flow with CNAME target in same partial zone
      A[Request to <code>sub1.partialzone.com</code>] --> B[<code>CNAME</code> record for <code>sub1.partialzone.com</code> to <code>sub2.partialzone.com</code>]
      subgraph Cloudflare
        B --> C[<code>A</code> record for <code>sub2.partialzone.com</code> to <code>192.0.2.1</code>]
      end
      C --> D[<code>192.0.2.1</code>]
      subgraph Authoritative DNS
      E[<code>A</code> record for <code>sub2.partialzone.com</code> to <code>192.0.2.4</code>]
      end

  
When you avoid this situation - meaning you do not have the **target** of the CNAME record within your partial zone - this DNS resolution would happen differently.

    flowchart TD
      accTitle: DNS resolution flow with CNAME target not in partial zone
      A[Request to <code>sub1.partialzone.com</code>] --> B[<code>CNAME</code> record for <code>sub1.partialzone.com</code> to <code>sub2.partialzone.com</code>]
      B --> C[<code>A</code> record for <code>sub2.partialzone.com</code> to <code>192.0.2.4</code>]
      C --> D[<code>192.0.2.4</code>]
      subgraph Cloudflare
        B
      end
      subgraph Authoritative DNS
        C
      end

---

## Records pointing to a partial zone within the same account

You could also [create a CNAME record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) in a zone (partial or full) that points to a record in another partial zone within your account.

In this case, Cloudflare will always resolve the CNAME target based on the value at your authoritative DNS provider of the CNAME target zone.

    flowchart TD
      accTitle: DNS resolution flow with CNAME target in a zone within the same account
      A[Request to <code>www\.alice.com</code>] --> B[<code>CNAME</code> record for <code>www\.alice.com</code> to <code>www\.partialzone.com</code>]
      B --> C[<code>A</code> record for <code>www\.partialzone.com</code> to <code>192.0.2.4</code>]
      C --> D[<code>192.0.2.4</code>]
      subgraph Cloudflare account
        subgraph Cloudflare zone 1
          B
        end
        subgraph Cloudflare zone 2
        E[<code>A</code> record for <code>www\.partialzone.com</code> to <code>203.0.113.1</code>]
        end
      end
      subgraph Authoritative DNS
      C
      end

### Auth DNS points to `cdn.cloudflare.net`

Considering the following scenario:

* The target zone (Cloudflare zone 2 in this example) is a partial zone and the DNS record on the partial zone is proxied.
* The DNS record on the authoritative DNS server points to `cdn.cloudflare.net`

If such setup is in place, the subdomain (`www.partialzone.com` in this example) will resolve to a Cloudflare proxy IP, which will ultimately result in an error. Consider using [custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/) and [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/) setup instead.

    flowchart TD
      accTitle: DNS resolution flow with CNAME target in a zone within the same account and auth DNS pointing to cdn.cloudflare.net
      A[Request to <code>www\.alice.com</code>] --> B[<code>CNAME</code> record for <code>www\.alice.com</code> to <code>www\.partialzone.com</code>]
      B --> C[<code>CNAME</code> record for <code>www\.partialzone.com</code> to <code>www\.partialzone.com.cdn.cloudflare.net</code>]
      C --> D[<code>Cloudflare proxy IP</code>]
      subgraph Cloudflare account
        subgraph Cloudflare zone 1
          B
        end
        subgraph Cloudflare zone 2
        E[Proxied <code>A</code> record for <code>www\.partialzone.com</code> to <code>203.0.113.1</code>]
        end
      end
      subgraph Authoritative DNS
      C
      end

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/partial-setup/","name":"CNAME setup (Partial)"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/partial-setup/dns-resolution/","name":"DNS resolution"}}]}
```

---

---
title: Setup
description: A CNAME setup (also known as partial) allows you to use Cloudflare's reverse proxy while maintaining your primary and authoritative DNS provider.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Setup

A CNAME setup (also known as partial setup) allows you to use [Cloudflare's reverse proxy](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/) while maintaining your primary and authoritative DNS provider.

Use this option to proxy only individual subdomains through Cloudflare when you cannot change your authoritative DNS provider. You will be able to create A, AAAA, and CNAME records, which are the DNS record types that can be [proxied](https://developers.cloudflare.com/dns/proxy-status/).

Availability

A CNAME setup (partial) is only available to customers on a Business or Enterprise plan. Partial setups are not supported on Cloudflare Registrar domains.

---

## Before you begin

1. Create a Cloudflare account and add your domain.
2. Choose **Business** or **Enterprise** as your plan.
3. If you are onboarding a new domain to Cloudflare, ignore the instructions to change your nameservers.
4. (Recommended) Plan for SSL/TLS certificates:  
If you are only using [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) prior to converting your zone, a certificate will be provisioned for your subdomains only after each of the respective DNS records ([step 3](#3-add-dns-records) below) are [proxied](https://developers.cloudflare.com/dns/proxy-status/). Refer to [Enable Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/enable-universal-ssl/#partial-dns-setup) for details.  
If your domain is sensitive to downtime, instead of using Universal SSL, consider using an [advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) with [delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/#setup).

## 1\. Convert your zone and review DNS records

* [ Dashboard ](#tab-panel-7993)
* [ API ](#tab-panel-7994)

Make sure you have the correct plan

Make sure your zone is on the Business or Enterprise plan. If you have Free or Pro, the options mentioned below will not be displayed.

1. On the **Overview** page, select **Convert to CNAME DNS Setup**.
2. Select **Convert** to confirm.
3. Save the information from the **Verification TXT Record**. If you lose the information, you can also access it on the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page, under **Verification TXT Record**.
4. Make sure that you have all the DNS records (A, AAAA, or CNAME) for subdomains that you want to proxy through Cloudflare.

If you are adding a zone for the first time via API you can add it directly with a `type` of `partial`, without converting it.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Zone Edit`
* `Zone DNS Edit`

Create Zone

```

curl "https://api.cloudflare.com/client/v4/zones" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "name": "example.com",

    "account": {

        "id": "YOUR_ACCOUNT_ID"

    },

    "type": "partial"

  }'


```

## 2\. Verify ownership for your domain

Add the **Verification TXT Record** at your authoritative DNS provider. Cloudflare will verify the TXT record and send a confirmation email. This can take up to a few hours.

Example verification record

A verification record for `example.com` might be:

| Type | Name                          | Content             |
| ---- | ----------------------------- | ------------------- |
| TXT  | cloudflare-verify.example.com | 966215192-518620144 |

Note

If your authoritative DNS provider automatically appends DNS record `name` fields with your domain, make sure to only insert `cloudflare-verify` as the record name. Otherwise, it may result in an incorrect record name, such as `cloudflare-verify.example.com.example.com`.

After creating the record, you can use this [Dig Web Interface link ↗](https://digwebinterface.com/?type=TXT&ns=auth&nameservers=) to search (`dig`) for `cloudflare-verify.<YOUR DOMAIN>` and validate if it is working.

The verification record must remain in place for as long as your domain is active on a CNAME setup on Cloudflare.

If your organization has multiple Cloudflare accounts, also consider using zone holds to have more control over [domain ownership](https://developers.cloudflare.com/dns/zone-setups/partial-setup/#domain-ownership).

## 3\. Add DNS records

1. At your authoritative DNS provider:  
   1. Create CNAME records pointing to `{your-hostname}.cdn.cloudflare.net` for every hostname you wish to proxy through Cloudflare.  
Example CNAME record at authoritative DNS provider  
The CNAME record for `www.example.com` would be:  
```  
www.example.com CNAME www.example.com.cdn.cloudflare.net  
```
2. Remove any previously existing A, AAAA, or CNAME records referencing the hostnames you want to proxy through Cloudflare. For these hostnames, leave only the records pointing to `{your-hostname}.cdn.cloudflare.net`.
3. Repeat this process for each subdomain that should be proxied to Cloudflare.

---

## Other record types

If you are preparing a conversion from CNAME setup (partial) to primary setup (full), or if you have a more specific use case, you can use the [Create DNS Record](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) API endpoint to create DNS records of any supported type.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/partial-setup/","name":"CNAME setup (Partial)"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/partial-setup/setup/","name":"Setup"}}]}
```

---

---
title: Records quick scan
description: How Cloudflare scans and imports DNS records automatically.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Records quick scan

To help all customers get started when a new zone is created, Cloudflare offers a DNS records quick scan.

Where to find the quick scan

On the dashboard, quick scan is only available as you are onboarding a new domain. Via API, you can manually invoke quick scan with the [Trigger DNS Records Scan endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/scan%5Ftrigger/).

## How quick scan works

The scan is built upon a list of recurring patterns of DNS records **Type** and **Name**, that Cloudflare identifies as being used in existing active zones.

Since DNS record names are automatically appended with the domain that the records are set for, two completely different domains - `example.com` and `domain.test`, for example - would probably have a few matches if the lists of DNS records on their zones were compared side by side and the criterion was **Type**/**Name** combination.

Example

DNS management for **example.com**:

| Type      | Name           | Content                |
| --------- | -------------- | ---------------------- |
| **A**     | **@**          | 192.0.2.0              |
| **CNAME** | **www**        | example.com            |
| **A**     | **mail**       | 192.0.2.100            |
| **MX**    | **@**          | mail.example.com       |
| _CNAME_   | _my-store1900_ | example-shop.saas.test |

DNS management for **domain.test**:

| Type      | Name                     | Content           |
| --------- | ------------------------ | ----------------- |
| **A**     | **@**                    | 192.0.2.8         |
| **CNAME** | **www**                  | domain.test       |
| _CNAME_   | _specific-internal-name_ | services.test.dev |
| **A**     | **mail**                 | 192.0.2.20        |
| **MX**    | **@**                    | mail.domain.test  |

The DNS records **Content** would be different for each zone but, based on record **Type** and **Name**, Cloudflare can identify recurring patterns and expect to find the same pairs when a new domain is added.

The [use cases section](#use-case-examples) below provides some examples of DNS records **Type**/**Name** combinations that the scan usually finds.

## Limitations

Since the DNS records quick scan is not tailored to the specific zone you are adding to Cloudflare, there can be cases where not all records are picked up.

For example, if you have very specific hostnames - such as `my-store1900.example.com` instead of `store.example.com` \- or if you have set up a [DKIM record ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/) that uses a more custom name - `this._domainkey` instead of `default._domainkey` \- it is expected that the scan will not find the specific DNS records.

Important

You should always [review your DNS records](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/#2-review-your-dns-records) and manually add any missing ones before changing your nameservers.

## Use case examples

### Address records

| Type | Name | Content | TTL   |
| ---- | ---- | ------- | ----- |
| A    | @    | <IPv4>  | <TTL> |

The value `@` indicates the domain apex - in the example above, `domain.test` or `example.com`.

Virtually all zones on a [primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/) are expected to have at least one [address record ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-a-record/) pointing to the IP address where the website or application is hosted.

### www records

| Type  | Name | Content  | TTL   |
| ----- | ---- | -------- | ----- |
| CNAME | www  | <TARGET> | <TTL> |

| Type | Name | Content | TTL   |
| ---- | ---- | ------- | ----- |
| A    | www  | <IPv4>  | <TTL> |

Since it is still common that visitors type `www.<DOMAIN>` in their browsers expecting to reach the domain, zones will usually have a [CNAME](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#cname) or an [A](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#a-and-aaaa) record named `www`. This allows queries for `www.<DOMAIN>` to return the expected result.

### Email records

| Type | Name | Mail server      | TTL   | Priority   |
| ---- | ---- | ---------------- | ----- | ---------- |
| MX   | @    | webmail.<DOMAIN> | <TTL> | <PRIORITY> |

| Type  | Name | Content  | TTL   |
| ----- | ---- | -------- | ----- |
| CNAME | mail | <TARGET> | <TTL> |

| Type | Name    | Content | TTL   |
| ---- | ------- | ------- | ----- |
| A    | webmail | <IPv4>  | <TTL> |

Mail exchanger (`MX`) and other record types combined with names like `mail`, `webmail`, or `smtp`, are also commonly found. As explained in the [Set up email records page](https://developers.cloudflare.com/dns/manage-dns-records/how-to/email-records/), there are several DNS records that can be used to make sure email reaches your mail server and to prevent other email senders from spoofing your domain.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/reference/dns-quick-scan/","name":"Records quick scan"}}]}
```

---

---
title: Zone status
description: Zone status values and what they mean.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Zone status

Review information on the different statuses that your [zone](https://developers.cloudflare.com/dns/concepts/#zone) can have after you [add your website or application](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) to Cloudflare.

Zone status is also referred to as domain status. An **active** domain status is a requirement for your [application services configurations](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) to be applied. Refer to [How Cloudflare works](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/) for details.

If your zone status changes, you will receive an email at the address associated with your account.

The following diagram gives you an overview of the different statuses applicable and how your zone may transition from one status to the other. For zones with an active paid subscription, the time to automatic deletion or purge may not correspond to this diagram. Refer to the sections below for details.

flowchart LR
accTitle: Zone status flow
accDescr: Diagram of the different statuses applicable to Cloudflare zones and the transitions from one status to the other.

A[Initializing]
B[Pending]
C[Active]
D[Moved]
E[Deleted]
F[Purged]

 A-- Plan <br />selection --> B
 B-- Zone <br />authentication --> C
 C-- DNS <br />checks fail --> D
 D-- Moved <br />for 7 days --> E
 E-- Deleted <br />for 7 days --> F

 B-- Pending for <br />28 days --> E
 A-- Initializing for 28 days --> E

Note

If you use the API to add your website or application to Cloudflare, your zone will be created directly in a **Pending** status. **Initializing** only applies to domains added via the dashboard.

## Initializing (Finish setup)

You have initiated the setup via dashboard, but did not select a plan for your zone. Your zone status is presented as **Finish setup** on the Cloudflare dashboard.

In this state, Cloudflare does not respond to any DNS queries for your domain.

If your zone is in **Finish setup** for over 28 days, it will be automatically [deleted](#deleted).

Note

If you have mistakenly added a zone to your account via dashboard, you can safely [remove it](https://developers.cloudflare.com/fundamentals/manage-domains/remove-domain/) after selecting the Free plan.

## Pending

Your zone status is presented as **Pending Nameserver Update** on the Cloudflare dashboard.

Cloudflare responds to DNS queries for pending zones on the assigned Cloudflare nameserver IPs, but your zone is still not active and cannot be used to [proxy traffic to Cloudflare](https://developers.cloudflare.com/dns/proxy-status/limitations/#pending-domains).

### Causes

* [Primary setup (Full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/): You have either not [changed your authoritative nameservers](https://developers.cloudflare.com/dns/nameservers/update-nameservers/) or your change has not yet been authenticated by Cloudflare.
* [CNAME setup (Partial)](https://developers.cloudflare.com/dns/zone-setups/partial-setup/): You have either not added the verification TXT record to your authoritative DNS provider or the record has not yet been authenticated by Cloudflare.
* [Cloudflare as Secondary DNS provider](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/): When you have either not [changed your authoritative nameservers](https://developers.cloudflare.com/dns/nameservers/update-nameservers/) to include the Cloudflare Secondary nameservers or your change has not yet been authenticated by Cloudflare.

After you add your domain, Cloudflare performs checks on a schedule to confirm you have updated your nameservers. The first check occurs after 60 seconds and the following attempts happen at gradually increased intervals. You can re-trigger the check [via API](https://developers.cloudflare.com/api/resources/zones/subresources/activation%5Fcheck/methods/trigger/) or on the Dashboard, in the respective domain [Overview page ↗](https://dash.cloudflare.com/?to=/:account/:zone/).

The activation check behavior depends on your zone setup:

| Zone setup                                                                                                                                                                                                                                                                                                                         | Activation requirement                                                                                                                              |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/) without [multi-provider DNS](https://developers.cloudflare.com/dns/nameservers/nameserver-options/#multi-provider-dns)                                                                                                                       | At the registrar (or parent zone), only the assigned Cloudflare nameservers must be listed. Any nameservers from other DNS providers cause failure. |
| [Primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/) with [multi-provider DNS](https://developers.cloudflare.com/dns/nameservers/nameserver-options/#multi-provider-dns) enabled, or [secondary setup](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) | At the registrar (or parent zone), the assigned Cloudflare nameservers must be present. Nameservers from other DNS providers are allowed.           |
| [CNAME setup (partial)](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)                                                                                                                                                                                                                                          | The verification TXT record must be present on your authoritative DNS provider. Nameservers at the registrar are not changed.                       |

### Expected behavior for different plans

If your domain is on the Free plan, it will be automatically deleted if it is not activated within 28 days.

Any pending zone with a paid plan (Pro, Business, Enterprise) will remain pending until the plan is removed, or the domain is activated or [removed from Cloudflare](https://developers.cloudflare.com/fundamentals/manage-domains/remove-domain/).

Do not use pending zones in production

Make sure not to use pending zones for production traffic. Cloudflare responds to DNS queries for pending zones on the assigned Cloudflare nameserver IPs but there are associated risks, especially if you do not use [zone holds](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/).

For Enterprise zones, if you want to adjust settings before zone activation, Logpush for [DNS logs](https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/zone/dns%5Flogs/) and [DNS Zone Transfer](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/) configuration work as expected in pending state.

## Active

Cloudflare has authenticated your [nameserver changes](https://developers.cloudflare.com/dns/nameservers/update-nameservers/) or [verification TXT record](https://developers.cloudflare.com/dns/zone-setups/partial-setup/setup/#2-verify-ownership-for-your-domain) and you can proxy domain traffic through Cloudflare. For more details refer to [How Cloudflare works](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/) and [Domain configurations](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/).

## Moved

Your domain has failed multiple DNS checks, where either the Cloudflare nameservers are no longer present on your domain's `NS` records ([Primary setup (Full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/)) or no `SOA` record is returned for the zone ([CNAME setup (Partial)](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)).

### Expected behavior for different plans

If your domain is on the Free plan, it will be automatically deleted 7 days after it entered the moved status.

For moved zones with a paid plan (Pro, Business, Enterprise), deletion will occur after 7 days if any of the following is observed:

* The paid plan is removed.
* The domain is activated in another Cloudflare account.

You can also [manually remove](https://developers.cloudflare.com/fundamentals/manage-domains/remove-domain/) your domain from Cloudflare.

## Deleted

Your zone has been archived. Cloudflare still responds to DNS queries for deleted zones on the assigned Cloudflare nameserver IPs (for non-deleted DNS records) and you can re-add the domain to Cloudflare by following the [regular onboarding flow](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/).

New nameserver assignment

When you re-add a previously deleted domain, Cloudflare assigns a new nameserver pair as a security measure. If you are not using Cloudflare Registrar, make sure to [update your registrar](https://developers.cloudflare.com/dns/nameservers/update-nameservers/) with the new nameservers after re-adding the domain. Refer to [nameserver assignment](https://developers.cloudflare.com/dns/nameservers/nameserver-options/#assignment-method) for details.

After being deleted for seven days, zones are automatically [purged](#purged).

## Purged

After a zone is deleted for seven days, it will be purged. Cloudflare does not respond to DNS queries for purged zones and, unlike [deleted zones](#deleted), this status cannot be reverted. In this case, even if you re-add the domain to the same Cloudflare account, none of the zone settings are expected to be restored.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/reference/domain-status/","name":"Zone status"}}]}
```

---

---
title: Zone removal
description: Remove a zone from your Cloudflare account.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Zone removal

If domains on Free zones remain in the [Pending](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/#pending) or [Moved](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/#moved) status for too long, Cloudflare automatically removes them from your account and the Cloudflare network. Refer to [zone statuses](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/) for more details.

You can also [manually remove a domain](https://developers.cloudflare.com/fundamentals/manage-domains/remove-domain/) from Cloudflare.

If you need to re-add a domain to your account, follow the [regular onboarding flow](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/). Cloudflare will assign a new nameserver pair when you re-add the domain, so you must [update your registrar](https://developers.cloudflare.com/dns/nameservers/update-nameservers/) with the new nameservers. Refer to [nameserver assignment](https://developers.cloudflare.com/dns/nameservers/nameserver-options/#assignment-method) for details.

Purged zones

By default, your zone will be automatically purged seven days after the removal. In this case, even if you re-add the domain to the same Cloudflare account, none of the zone settings are expected to be restored. Refer to [zone statuses](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/) for more details.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/removal/","name":"Zone removal"}}]}
```

---

---
title: Subdomain setup
description: Add a subdomain as a standalone zone in Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Subdomain setup

When you use a subdomain setup, you can manage the [Cloudflare configurations](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/) for one or more subdomains separately from those associated with your apex domain. This means that, on your [account homepage ↗](https://dash.cloudflare.com/?to=/:account/), you would find websites like `example.com` or `blog.example.com` listed as separate zones.

Note

This is different from simply creating a subdomain for a site you already have in Cloudflare. If you do not need separate Cloudflare configuration for your subdomain, refer to [Create a subdomain record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-subdomain/).

You might use this setup when you want to share access to a specific subdomain's settings with different teams, but have stricter controls on your apex domain. For example, a subdomain setup could allow your documentation team to manage the Cloudflare configuration for `docs.example.com`, while preventing them from adjusting any settings on `example.com`.

Subdomain setups are also useful when different subdomains require entirely different settings. For example, you may have different requirements for `docs.example.com`, `blog.example.com`, and `community.example.com`.

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | No  | No       | No         | Yes |

Setup combinations

The availability of different setups depends on both the parent zone setup and the setup used for the child zone. Review the [available setups](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/setup/#available-setups) to understand what combinations are supported.

### Access applications

To use subdomain setups with [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/access-controls/policies/), note that:

* If the child zone is in a pending state when you create the Access application, your configuration will not automatically apply when you activate the zone. You must also re-save the Access application once your subdomain setup is active.
* If you split out a subdomain which already has an Access application, you will also need to re-save the Access application to associate it with the new child zone.

## Resources

* [ Setup ](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/setup/)
* [ Enable DNSSEC ](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/dnssec/)
* [ Migrate to new account ](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/move-to-new-account/)
* [ Rollback ](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/rollback/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/subdomain-setup/","name":"Subdomain setup"}}]}
```

---

---
title: Enable DNSSEC
description: Enable DNSSEC for a subdomain zone.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Enable DNSSEC

As opposed to the [normal process](https://developers.cloudflare.com/dns/dnssec/) for enabling DNSSEC, DNSSEC with a subdomain setup requires a few additional steps.

## Requirements

To use DNSSEC for a subdomain setup, DNSSEC must be enabled on the parent zone. After enabling DNSSEC on the parent zone, you should wait the minimum TTL value (specified in the [SOA record ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-soa-record/) of the parent zone) to ensure DNS resolvers provide the same DNS query responses.

## Setup

1. [Create](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/setup/#how-to) the child zone.
2. Make sure the child zone is [active](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/) on Cloudflare and that DNS resolution is working properly for your subdomain.
3. [Enable DNSSEC](https://developers.cloudflare.com/dns/dnssec/) for the child zone and save the information provided within the DS record output.
4. On the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page of the parent zone, [add the DS record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) from the previous step.  
![Screenshot showing how to add a DS record within Cloudflare](https://developers.cloudflare.com/_astro/ds-record-example.eCudbis6_1s6vlD.webp)
5. Add an A record to the child zone to validate DNS resolution.
6. Wait two to six hours. Then, [test the A record](https://developers.cloudflare.com/dns/dnssec/troubleshooting/#test-dnssec-with-dig) added in the previous step using multiple DNS resolvers with DNSSEC validation (`1.1.1.1`, `8.8.8.8`, and `9.9.9.9`). For example, if the A record is for `test.child.example.com`: `dig test.child.example.com +dnssec @1.1.1.1`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/subdomain-setup/","name":"Subdomain setup"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/subdomain-setup/dnssec/","name":"Enable DNSSEC"}}]}
```

---

---
title: Migrate to new account
description: Move a subdomain zone to a different Cloudflare account.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Migrate to new account

When using a [subdomain setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/), you can have your subdomain as a separate zone within the same account as the parent domain or within a different account.

If you have already [created a standalone subdomain zone](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/setup/) within the same account, you can still move it to a separate account.

1. [Add the subdomain](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) to a new Cloudflare account.
2. In the original subdomain zone, [export](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/#export-records) the DNS records.
3. Review the exported records, delete any unnecessary ones, and [import](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/#import-records) them into the new subdomain zone.
4. Update the `NS` records in the parent zone to refer to the newly assigned nameservers of the child zone.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/subdomain-setup/","name":"Subdomain setup"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/subdomain-setup/move-to-new-account/","name":"Migrate to new account"}}]}
```

---

---
title: Rollback
description: Roll back a subdomain zone setup.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Rollback

Refer to the following process to understand how you can rollback a [subdomain setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/) and recreate the corresponding subdomain DNS records in an existing parent zone within Cloudflare.

## Before you begin

* This guide assumes both your child domain (`blog.example.com`) and its parent domain (`example.com`) are in Cloudflare.
* In the child zone, review and [export](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/#export-records) the DNS records.

Important

This process may incur in downtime, as it is not possible to add address records (A/AAAA) while still having [corresponding NS records at the same name](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/existing-ns-record/) within the parent zone.

## Steps

1. (Optional) In the parent zone, migrate over any settings - [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/), [Rules](https://developers.cloudflare.com/rules/), [Workers](https://developers.cloudflare.com/workers/), and more - that might be needed for the child domain.
2. (Optional) If necessary, [order an advanced SSL certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) that covers the child domain and any deeper subdomains.
3. In the parent zone, go to the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page.
4. Delete one of the `NS` records defined for the child domain.
5. Edit the remaining `NS` record to create the subdomain address record.
6. [Import](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/#import-records) the records you had obtained [before you began](#before-you-begin).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/subdomain-setup/","name":"Subdomain setup"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/subdomain-setup/rollback/","name":"Rollback"}}]}
```

---

---
title: Setup
description: Set up a subdomain zone in Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Setup

Availability

Subdomain setup is only available for Enterprise accounts. If you only want to create a subdomain for your site in Cloudflare, refer to [Create a subdomain record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-subdomain/).

[Subdomain setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/) relies on a process known as delegation. When, in a parent domain such as `example.com`, an [NS record ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-ns-record/) is created for a subdomain `blog.example.com`, this means that DNS management for the subdomain can be done separately, in its own [DNS zone](https://developers.cloudflare.com/dns/concepts/#zone).

    flowchart TD
      accTitle: Example of parent zone and subdomains
      A[<code>example.com</code>] --> B[<code>docs.example.com</code>]
      A[<code>example.com</code>] --> C[<code>blog.example.com</code>]
      subgraph Parent domain
        A
      end
      subgraph Subdomains
        B
        C
      end

---

## Available setups

When configuring a subdomain setup, its availability will depend on both the parent zone setup and the setup used for the child zone. A child zone holds DNS management for a delegated subdomain.

| Parent zone                                                                                                                                                                     | Child zone                                                                                             | Available |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | --------- |
| [Full](https://developers.cloudflare.com/dns/zone-setups/full-setup/) or [Secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) | [Full](https://developers.cloudflare.com/dns/zone-setups/full-setup/)                                  | Yes       |
| [Full](https://developers.cloudflare.com/dns/zone-setups/full-setup/) or [Secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) | [Secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) | Yes       |
| [Full](https://developers.cloudflare.com/dns/zone-setups/full-setup/) or [Secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) | [Partial](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)                            | No        |
| [Partial](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)                                                                                                     | [Full](https://developers.cloudflare.com/dns/zone-setups/full-setup/)                                  | Yes       |
| [Partial](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)                                                                                                     | [Secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) | Yes       |
| [Partial](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)                                                                                                     | [Partial](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)                            | Yes       |

Subdomain zones in partial setup are not delegated

Subdomains using a CNAME setup (partial) represent an exception in the sense that delegation does not apply in this context. As explained in the dedicated [CNAME setup (Partial) section](https://developers.cloudflare.com/dns/zone-setups/partial-setup/), this setup is intended to simply proxy individual subdomains through Cloudflare. For completeness, however, this is listed as an option in this table and the [how-to guide](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/setup/parent-on-partial/) has detailed explanation on how to achieve a subdomain zone using a CNAME setup (partial).

This table assumes zones that are in an [active status](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/). For example, if you need to add the parent zone to Cloudflare when its child zone already exists in a CNAME setup (partial), you can [convert the parent zone to a CNAME setup (partial)](https://developers.cloudflare.com/dns/zone-setups/partial-setup/setup/#1-convert-your-zone-and-review-dns-records) while it is still in pending status.

---

## How to

Refer to the following guides to learn how to configure a subdomain setup depending on the setup used for the parent zone:

* [ Parent zone on full setup ](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/setup/parent-on-full/)
* [ Parent zone on partial setup ](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/setup/parent-on-partial/)

Although the how-to guides in this documentation are focused on both parent domains and subdomains existing in Cloudflare, it is also possible to achieve a subdomain setup in Cloudflare while the parent domain exists in a different DNS provider.

---

## SSL/TLS certificates

When using subdomain setup, you should consider possible interactions between parent zone and child zone configurations that could impact [SSL/TLS certificates](https://developers.cloudflare.com/ssl/) provisioning.

If a certificate is already active on the child zone for a specific hostname (`subdomain.example.com`), any certificate pack containing that exact hostname in the parent zone (`example.com`) will fail validation.

## Access applications

To use subdomain setups with [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/access-controls/policies/), note that:

* If the child zone is in a pending state when you create the Access application, your configuration will not automatically apply when you activate the zone. You must also re-save the Access application once your subdomain setup is active.
* If you split out a subdomain which already has an Access application, you will also need to re-save the Access application to associate it with the new child zone.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/subdomain-setup/","name":"Subdomain setup"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/subdomain-setup/setup/","name":"Setup"}}]}
```

---

---
title: Parent zone on full setup
description: Set up subdomain zone when parent uses full setup.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Parent zone on full setup

When the parent zone is using a [primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/)[1](#user-content-fn-1), the steps to set up your child zone depend on whether the subdomain already exists in the parent domain.

Note

The following steps are similar if your Cloudflare parent zone is in a secondary setup, with the only difference that you will use your external primary DNS provider to make any necessary adjustments to DNS records.

## Subdomain does not exist

If you have not yet created DNS records covering your subdomain in the parent zone:

1. Add the subdomain to a Cloudflare account as a new zone. It can be the same account where the parent zone exists or a different one.
2. Complete the configuration accordingly for [full](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/) or [secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/) setup.
3. Get the nameserver names for the subdomain. These can be found within your newly created child zone on the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page, and will **not** be the same nameservers as the ones used in the parent zone.
4. On the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page of the parent zone, [add](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) two `NS` records for the subdomain you want to delegate.  
For example, if you delegated `www.example.com`, you might add the following records to `example.com`:  
| **Type** | **Name** | **Content**               |  
| -------- | -------- | ------------------------- |  
| NS       | www      | john.ns.cloudflare.com    |  
| NS       | www      | melinda.ns.cloudflare.com |
5. After a few minutes, the child zone will be active.
6. Create the various DNS records needed for your child zone.
7. (Optional) [Enable DNSSEC](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/dnssec/) on the child zone.

## Subdomain already exists

If you have already created DNS records covering your subdomain in the parent zone:

1. Add the subdomain to a Cloudflare account as a new zone. It can be the same account where the parent zone exists or a different one.
2. Complete the configuration accordingly for [full](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/) or [secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/) setup.
3. In your child zone, make sure you have all DNS records that relate to the subdomain. This includes all DNS records deeper than the delegated subdomain. For example, if you are delegating `www.example.com`, you should also move over records for `api.www.example.com`.  
Note  
If your child zone is on a primary setup (full), consider [exporting](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/#export-records) records from the parent zone, deleting all unnecessary records, and then [importing](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/#import-records) the records into your new zone.
4. If the parent zone is on Cloudflare, make sure that you migrate over any settings ([WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/), [Rules](https://developers.cloudflare.com/rules/), [Workers](https://developers.cloudflare.com/workers/), and more) that might be needed for the child zone.
5. In the child zone, [order an advanced SSL certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) that covers the child subdomain and any deeper subdomains (if present).
6. Get the nameserver names for the subdomain. These can be found within your newly created child zone on the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page, and will **not** be the same nameservers as the ones used in the parent zone.  
Note  
If the parent zone is on Cloudflare, steps 7 and 9 below can be achieved via API. Use the [Batch DNS records](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/batch/) endpoint to delete and create or update DNS records within a single request. Refer to [Batch record changes](https://developers.cloudflare.com/dns/manage-dns-records/how-to/batch-record-changes/) for further guidance.
7. On the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page of the parent zone, update existing address records (`A/AAAA`) on your subdomain to `NS` records. If you only have one address record, update the existing one and add a new `NS` record. If you have multiple address records, update any two of them.  
For example, to delegate the subdomain `www.example.com`, the updated records in the parent zone `example.com` should contain `NS` records similar to the following:  
| **Type** | **Name** | **Content**            |  
| -------- | -------- | ---------------------- |  
| NS       | www      | john.ns.cloudflare.com |  
| NS       | www      | adam.ns.cloudflare.com |  
In this example, `john.ns.cloudflare.com` and `adam.ns.cloudflare.com` represent the subdomain nameservers that you got from step 6.
8. Flush the address records of your subdomain in public resolvers ([1.1.1.1 ↗](https://1.1.1.1/purge-cache/) and [8.8.8.8 ↗](https://developers.google.com/speed/public-dns/cache)).
9. On the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page of the parent zone, [delete](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#delete-dns-records) all the remaining records on the delegated subdomain, except the `NS` records that you created in step 7.  
Also delete all DNS records deeper than the delegated subdomain. For example, if you are delegating `www.example.com`, records for `api.www.example.com` should only exist in the new child zone.
10. Within a short period of time, the child zone should be active.
11. (Optional) [Enable DNSSEC](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/dnssec/) on the child zone.

## Footnotes

1. Meaning that Cloudflare is your Authoritative DNS provider. [↩](#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":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/subdomain-setup/","name":"Subdomain setup"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/subdomain-setup/setup/","name":"Setup"}},{"@type":"ListItem","position":6,"item":{"@id":"/dns/zone-setups/subdomain-setup/setup/parent-on-full/","name":"Parent zone on full setup"}}]}
```

---

---
title: Parent zone on partial setup
description: Set up subdomain zone when parent uses partial setup.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Parent zone on partial setup

When the parent zone is using a [CNAME setup (partial)](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)[1](#user-content-fn-2), the steps to set up your child zone depend on whether the subdomain already exists in the parent domain.

## Subdomain does not exist

If you have not yet created a DNS record covering your subdomain in the parent zone:

* [ child is full or secondary ](#tab-panel-7995)
* [ child is partial ](#tab-panel-7996)

1. Add the subdomain to a Cloudflare account as a new zone. It can be the same account where the parent zone exists or a different one.
2. Complete the configuration accordingly for [full](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/) or [secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/) setup.
3. After creating the DNS records on the child zone, add the Cloudflare nameservers as `NS` records at your external DNS provider.
4. Within a short period of time, the child zone should be active.

1. Add the subdomain to a Cloudflare account as a new zone. It can be the same account where the parent zone exists or a different one.
2. Select either Business or Enterprise as your zone plan and complete the onboarding flow according to your needs.
3. On the [Overview page ↗](https://dash.cloudflare.com/?to=/:account/:zone), select **Convert to CNAME DNS Setup**.
4. Confirm that you have created all the [DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) needed for your child zone.
5. On the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page, get the **Verification TXT Record** and add it at your authoritative DNS provider.

Example verification record

A verification record for `sub.example.com` might be:

| Type | Name                              | Content             |
| ---- | --------------------------------- | ------------------- |
| TXT  | cloudflare-verify.sub.example.com | 966215192-518620144 |

If your authoritative DNS provider automatically appends DNS record `name` fields with your domain, make sure to only insert `cloudflare-verify` as the record name. Otherwise, it may result in an incorrect record name, such as `cloudflare-verify.sub.example.com.sub.example.com`.

After creating the record, you can use this [Dig Web Interface link ↗](https://digwebinterface.com/?type=TXT&ns=auth&nameservers=) to search (`dig`) for `cloudflare-verify.<YOUR DOMAIN>` and validate if it is working.

That record must remain in place for as long as your subdomain is active on the CNAME setup (partial) on Cloudflare.

1. Within a short period of time, the child zone should be active.
2. At your authoritative DNS provider, add `CNAME` records pointing to `{your-hostname}.cdn.cloudflare.net` for the subdomain you have added and any deeper subdomain records you want to proxy through Cloudflare.

Example CNAME record at authoritative DNS provider

The `CNAME` record for `sub.example.com` would be:

```

sub.example.com CNAME sub.example.com.cdn.cloudflare.net


```

## Subdomain already exists

If you have already created a DNS record covering your subdomain in the parent zone:

* [ child is full or secondary ](#tab-panel-7997)
* [ child is partial ](#tab-panel-7998)

1. Add the subdomain to a Cloudflare account as a new zone. It can be the same account where the parent zone exists or a different one.
2. Complete the configuration accordingly for [full](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/) or [secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/) setup.
3. In your child zone, [re-create all DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) that relate to your subdomain. This includes all DNS records deeper than the delegated subdomain, meaning that if you are delegating `www.example.com`, you should also move over records for `api.www.example.com`.  
Note  
If your child zone is on a primary setup (full), consider [exporting](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/#export-records) records from the parent zone, deleting all unnecessary records, and then [importing](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/#import-records) the records into your new zone.
4. Make sure that you migrate over any settings ([WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/), [Rules](https://developers.cloudflare.com/rules/), [Workers](https://developers.cloudflare.com/workers/), and more) that might be needed for the child zone.
5. In the child zone, [order an advanced SSL certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) that covers the child subdomain and any deeper subdomains.
6. Get the Cloudflare nameservers for the subdomain and add them as `NS` records at your external DNS provider.
7. Within a short period of time, the child zone should be active.
8. On the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page of the parent zone, [delete](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#delete-dns-records) any `A`, `AAAA`, or `CNAME` records referencing the subdomain or any of its deeper subdomains.

1. Add the subdomain to a Cloudflare account as a new zone. It can be the same account where the parent zone exists or a different one.
2. Select either Business or Enterprise as your zone plan and complete the onboarding flow according to your needs.
3. On the [Overview page ↗](https://dash.cloudflare.com/?to=/:account/:zone), select **Convert to CNAME DNS Setup**.
4. In your child zone, [re-create all DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) that relate to your subdomain. This includes all DNS records deeper than the subdomain you used to create the zone - if you are creating a zone for `www.example.com`, you should also move over records for `api.www.example.com`.  
Note  
Cloudflare recommends [exporting](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/#export-records) records from the parent zone, deleting all unnecessary records, and then [importing](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/#import-records) the records into your new zone.
5. Make sure that you migrate over any settings ([WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/), [Rules](https://developers.cloudflare.com/rules/), [Workers](https://developers.cloudflare.com/workers/), and more) that might be needed for the child zone.
6. In the child zone, [order an advanced SSL certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) that covers the child subdomain and any deeper subdomains.
7. On the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page, get the **Verification TXT Record** and add it at your authoritative DNS provider.

Example verification record

A verification record for `sub.example.com` might be:

| Type | Name                              | Content             |
| ---- | --------------------------------- | ------------------- |
| TXT  | cloudflare-verify.sub.example.com | 966215192-518620144 |

If your authoritative DNS provider automatically appends DNS record `name` fields with your domain, make sure to only insert `cloudflare-verify` as the record name. Otherwise, it may result in an incorrect record name, such as `cloudflare-verify.sub.example.com.sub.example.com`.

After creating the record, you can use this [Dig Web Interface link ↗](https://digwebinterface.com/?type=TXT&ns=auth&nameservers=) to search (`dig`) for `cloudflare-verify.<YOUR DOMAIN>` and validate if it is working.

That record must remain in place for as long as your subdomain is active on the CNAME setup (partial) on Cloudflare.

1. Within a short period of time, the child zone should be active.
2. On the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page of the parent zone, [delete](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#delete-dns-records) any previous `A`, `AAAA`, or `CNAME` records referencing the subdomain or any of its deeper subdomains.
3. At your authoritative DNS provider, confirm you have `CNAME` records pointing to `{your-hostname}.cdn.cloudflare.net` for the subdomain you have added and any deeper subdomain records you want to proxy through Cloudflare.

Example CNAME record at authoritative DNS provider

The `CNAME` record for `sub.example.com` would be:

```

sub.example.com CNAME sub.example.com.cdn.cloudflare.net


```

## Footnotes

1. Meaning that another DNS provider - not Cloudflare - maintains your Authoritative DNS. [↩](#user-content-fnref-2)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/subdomain-setup/","name":"Subdomain setup"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/subdomain-setup/setup/","name":"Setup"}},{"@type":"ListItem","position":6,"item":{"@id":"/dns/zone-setups/subdomain-setup/setup/parent-on-partial/","name":"Parent zone on partial setup"}}]}
```

---

---
title: Cannot add domain
description: Troubleshoot issues when adding a domain to Cloudflare, including DNSSEC conflicts, registrar errors, and restriction codes.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cannot add domain

If you encounter issues [adding a domain](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) to Cloudflare, follow these troubleshooting steps.

## Disable DNSSEC

Cloudflare cannot provide authoritative DNS resolution for a domain — a [domain on a primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/) — when **DNSSEC** is enabled at your domain registrar.

If you do not disable **DNSSEC** before changing your nameservers, you might experience the following issues:

* DNS does not resolve after switching to Cloudflare's nameservers.
* DNS query response status is `SERVFAIL`.
* The domain remains in a [Pending status](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/).

If you experience these issues, refer to [Configuring DNSSEC](https://developers.cloudflare.com/dns/dnssec) and [Troubleshooting DNSSEC](https://developers.cloudflare.com/dns/dnssec/troubleshooting/).

---

## Register the domain

If the issue is with your registrar, you may receive the following error messages:

* `exampledomain.com is not a registered domain (Code: 1049)`
* `We were unable to identify bad.psl-example as a registered domain. Please ensure you are providing the root domain and not any subdomains (e.g., example.com, not subdomain.example.com) (Code: 1099)`
* `Failed to lookup registrar and hosting information of exampledomain.com at this time. Please contact Cloudflare Support or try again later. (Code: 1110)`

If you receive these error messages, make sure that:

* You are providing the apex domain (also known as "root domain", e.g. `example.com`) and not a subdomain (`www.example.com`).
* Your domain is fully registered and its registration data lists its nameservers.
* Your domain uses a verified [top-level domain (TLD) ↗](https://publicsuffix.org/list/).

---

## Resolve DNS for apex domain

Before a domain can be added to Cloudflare, the domain must return `NS` records for valid, working nameservers. `NS` records can be checked via third-party online tools such as [https://www.whatsmydns.net ↗](https://www.whatsmydns.net/) or via a command-line terminal using a dig command:

Terminal window

```

dig +short ns cloudflare.com


```

```

ns3.cloudflare.com.

ns4.cloudflare.com.

ns5.cloudflare.com.

ns6.cloudflare.com.

ns7.cloudflare.com.


```

Additionally, the domain must return a valid `SOA` record when queried. `SOA` records can be checked via third-party online tools such as [https://www.whatsmydns.net ↗](https://www.whatsmydns.net/) or via a command-line terminal:

Terminal window

```

dig +short soa cloudflare.com


```

```

ns3.cloudflare.com. dns.cloudflare.com. 2029202248 10000 2400 604800 300


```

---

## Check if the domain is restricted at Cloudflare

If Cloudflare has temporary or permanent restrictions on a domain, you will receive the following errors:

* **Error 1105**  
   * **Message**: `Error with Cloudflare request: [1105] This zone is temporarily restricted and cannot be added to Cloudflare at this time, please contact Cloudflare Support.`  
   * **Cause**: We have seen too many attempts to add a domain to Cloudflare  
   * **Resolution**: Wait 3 hours before attempting to re-add the domain to Cloudflare. Support cannot speed up this process.
* **Error 1093 or 1116**  
   * **Message**: `This zone cannot be added to Cloudflare at this time, please contact Cloudflare Support. (Code: 1093)`  
   * **Cause**: You may have entered a subdomain (`www.example.com`) instead of the apex domain (also known as "root domain", e.g. `example.com`).  
   * **Resolution**: Verify that you are entering the apex domain. If you are and still experience issues, contact [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/).
* **Error 1097**  
   * **Message**: `This web property cannot be added to Cloudflare at this time. If you are an Enterprise customer, contact your Customer Success Manager. Otherwise, email abusereply@cloudflare.com with a detailed explanation of your association with this zone. (Code: 1097)`  
   * **Resolution**: Contact [abusereply@cloudflare.com](mailto:abusereply@cloudflare.com) with a detailed explanation of your association with this zone.
* **Error: Cannot be found** OR **`<your domain>` is not a registered domain (code: 1049)**  
   * This can happen if the domain has not been registered yet. Some domains, like `.gov` domains, have special requirements that require the domain be added first.  
   * **Resolution:** Contact [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) if you require assistance adding a `.gov` and/or other domains that require manual registration.

---

## Contact the zone owner in case of zone hold error

Enterprise customers can use the [zone hold](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/) feature to prevent domains to be added in any other account. If you get the following error when adding your domain, it means that a zone hold is active:

```

The zone name provided is subject to a hold which disallows the creation of this zone.

Please contact the owner of the Cloudflare account that manages this domain to have this hold removed.


```

In this case, you need to remove the zone hold if you own the Cloudflare account in which the zone is active, or contact the owner of the Cloudflare account that has the zone active.

If you are not the owner of the Cloudflare account that has the hold on the zone, using an online WHOIS tool might help you finding the owner of a website.

See this [external WHOIS tool ↗](https://www.godaddy.com/whois) or this [other external tool ↗](https://www.whois.com/whois/).

The owner might be your hosting provider, or a SaaS service provider.

You can also use the [Cloudflare Forgot Email? ↗](https://dash.cloudflare.com/forgot-email) page, and check the documentation related to the [Forgot Email? feature](https://developers.cloudflare.com/fundamentals/user-profiles/change-password-or-email/#forgot-your-email-address).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/troubleshooting/cannot-add-domain/","name":"Cannot add domain"}}]}
```

---

---
title: Delete all DNS records
description: Learn how to bulk delete DNS records in Cloudflare with a script so you can start from zero instead of using the quick scan results.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Delete all DNS records

When you connect your domain to Cloudflare, the [DNS records quick scan](https://developers.cloudflare.com/dns/zone-setups/reference/dns-quick-scan/) may automatically add several records to your zone.

If you realize most of them are not applicable and want to bulk delete DNS records, follow the steps below. This method assumes you are familiar with [API calls fundamentals](https://developers.cloudflare.com/fundamentals/api/).

Bulk deletion available in the dashboard

You can delete records in bulk via the dashboard, which removes the need for custom scripts as the one below. Refer to [Batch record changes](https://developers.cloudflare.com/dns/manage-dns-records/how-to/batch-record-changes/#delete-records-in-bulk) for details.

1. Make sure you have [an API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) that allows you to edit DNS for your zone.
2. Get your [zone ID](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/).
3. Run the following script, replacing `<ZONE_ID>` and `<API_TOKEN>` with the values you got from the previous steps.

Warning

This script uses [jq ↗](https://jqlang.github.io/jq/) to format `JSON` outputs for readability. Refer to [Make API calls](https://developers.cloudflare.com/fundamentals/api/how-to/make-api-calls/) for details.

Terminal window

```

zoneid=<ZONE_ID>

bearer=<API_TOKEN>

curl --silent "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records?per_page=50000" \

--header "Authorization: Bearer $bearer" \

| jq --raw-output '.result[].id' | while read id

do

  curl --silent --request DELETE "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records/$id" \

--header "Authorization: Bearer $bearer"

done


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/troubleshooting/delete-all-records/","name":"Delete all DNS records"}}]}
```

---

---
title: Domain deleted from Cloudflare
description: Learn why a domain may be removed from Cloudflare and how to recover it using audit logs and registrar verification.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Domain deleted from Cloudflare

Domain deletion commonly occurs for the following reasons:

* A user with access to the domain removed it.
* The nameservers no longer point to Cloudflare. Cloudflare continuously monitors domain registration.
* The domain was not authenticated (pending for 28 days).

---

## Check Audit Logs

Cloudflare [Audit Logs](https://developers.cloudflare.com/fundamentals/account/account-security/review-audit-logs/) contain information about domain deletion.

Note

_Delete_ is an **Action** that denotes domain deletion but is also commonly used for deletion of other various account settings. Therefore, ensure that **Resource** says _Zone_.

---

## Check registrar for Cloudflare nameservers

If your domain was using a [primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/), your registrar needs to use Cloudflare nameservers as the authoritative nameservers for your domain.

1. Use either the command-line based `whois` application provided with your operating system or a website such as [ICANN Lookup ↗](https://lookup.icann.org/).  
   * If you are unable to find the nameserver details for your domain, reach out to your domain registrar or domain provider to provide the domain registration information.  
   * Ensure Cloudflare's nameservers are the only two nameservers listed in the domain registration details.  
   * Ensure nameservers are spelled correctly in the domain registration.
2. Confirm that the nameservers exactly match the nameservers provided within the **Cloudflare Nameservers** card on the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page.
3. If you identify incorrect information, log in to your domain provider's portal to make updates or contact your domain provider for assistance.

---

## Recover a deleted domain

To recover a deleted domain, [re-add it in Cloudflare](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) just like you would for a new domain.

Warning

Cloudflare support is unable to restore DNS or settings for deleted domains.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/troubleshooting/domain-deleted/","name":"Domain deleted from Cloudflare"}}]}
```

---

---
title: Zone stuck in Pending Nameserver Update
description: Troubleshoot a Cloudflare zone that stays in Pending Nameserver Update status after changing nameservers, including stale DNSSEC DS records.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Zone stuck in Pending Nameserver Update

If your nameservers are correctly set to Cloudflare but your zone remains in **Pending Nameserver Update** status, stale DNSSEC DS records at your registrar are the most common cause.

## Stale DNSSEC DS records

DS records belong to your **registrar** (where the domain is registered), not to Cloudflare. When you change DNS providers, DS records from the previous provider often remain at the registrar and cause Cloudflare's zone verification to fail.

**To check for stale DS records:**

Terminal window

```

dig DS yourdomain.com


```

If DS records are returned and you did not configure Cloudflare DNSSEC, these are stale records from your previous provider.

**To remove stale DS records:**

1. Log in to your domain registrar's control panel.
2. Find DNSSEC settings (may be under **Advanced DNS** or **Security**).
3. Remove all existing DS records.
4. Wait up to 24 hours for the DS removal to propagate.

After the stale DS records are removed and expire from cache, your Cloudflare zone will activate automatically. You can then turn on DNSSEC in the Cloudflare dashboard if needed.

For more information on DNSSEC configuration, refer to [Configure DNSSEC](https://developers.cloudflare.com/dns/dnssec/) and [Troubleshoot DNSSEC](https://developers.cloudflare.com/dns/dnssec/troubleshooting/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/troubleshooting/pending-nameservers/","name":"Zone stuck in Pending Nameserver Update"}}]}
```

---

---
title: DNS Zone transfers
description: Transfer DNS zones between Cloudflare and other providers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNS Zone transfers

Zone transfers allow you to use multiple DNS providers for the same domain to increase availability and fault tolerance. If one provider has an outage, the other can still answer DNS queries, keeping your domain available.

With zone transfers, your providers synchronize DNS records between themselves using one of two protocols:

* **Authoritative zone transfer ([AXFR ↗](https://www.rfc-editor.org/rfc/rfc5936.html))**: Copies the entire zone from the primary to the secondary provider, even if only one record changes.
* **Incremental zone transfer ([IXFR ↗](https://www.rfc-editor.org/rfc/rfc1995.html))**: Transfers only the changes since the last transfer, rather than the entire zone.

Cloudflare supports both protocols.

You have two configuration options for zone transfers:

* [Cloudflare as Primary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-primary/): Cloudflare is your primary DNS provider and performs outgoing zone transfers to your secondary DNS provider(s).
* [Cloudflare as Secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/): Cloudflare is your secondary DNS provider and initiates incoming zone transfers from your primary DNS provider.

## Peer DNS server

A peer DNS server is the external DNS provider that participates in zone transfers with Cloudflare. The same peer can be linked to multiple primary and secondary zones. Each peer can be associated with only one Transaction Signature (TSIG) — an authentication mechanism that uses a shared secret to verify zone transfer messages between providers.

The maximum number of linked peers per zone is 30.

You can manage peers via the [API](https://developers.cloudflare.com/api/resources/dns/subresources/zone%5Ftransfers/subresources/peers/methods/list/) or the dashboard:

1. In the Cloudflare dashboard, go to the account **Settings** page.  
[ Go to **Configurations** ](https://dash.cloudflare.com/?to=/:account/configurations)
2. Refer to **DNS Settings** \> **DNS Zone Transfers**.

The fields below configure how Cloudflare communicates with the peer. When Cloudflare is primary, it sends NOTIFY messages to alert the peer that zone data has changed. When Cloudflare is secondary, it sends AXFR/IXFR requests to retrieve updated records from the peer.

| Field        | Cloudflare as Primary (Outgoing)                            | Cloudflare as Secondary (Incoming)                       |
| ------------ | ----------------------------------------------------------- | -------------------------------------------------------- |
| Name         | Human readable name of peer                                 | Human readable name of peer                              |
| IP           | If configured, where Cloudflare sends the NOTIFY to         | Where Cloudflare sends the AXFR/IXFR transfer request to |
| Port         | IP Port for NOTIFY IP                                       | IP Port for transfer IP                                  |
| TSIG ID      | Attached TSIG object                                        | Attached TSIG object                                     |
| IXFR enabled | Cloudflare always supports IXFR for outgoing zone transfers | Specifies if Cloudflare only sends AXFR or AXFR and IXFR |

## Availability

Zone transfers are only available to customers on an Enterprise plan.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/zone-transfers/","name":"DNS Zone transfers"}}]}
```

---

---
title: Access Control Lists (ACLs)
description: Manage access control lists for DNS zone transfers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Access Control Lists (ACLs)

Access Control Lists (ACLs) define allowed source IP addresses from where servers accept incoming data or control messages.

When setting up new DNS zone transfers ([incoming](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) or [outgoing](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-primary/)), you will need to update the ACL at your other DNS provider(s) to allow Cloudflare to communicate with their server(s). You can find the Cloudflare IP addresses you need to allow at your other DNS provider(s) at [Cloudflare IP addresses](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/access-control-lists/cloudflare-ip-addresses/).

For your Cloudflare account, you only need to [create a new ACL](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/access-control-lists/create-new-list/) if you want to specify additional NOTIFY IPs that Cloudflare should listen to.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/zone-transfers/","name":"DNS Zone transfers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/zone-transfers/access-control-lists/","name":"Access Control Lists (ACLs)"}}]}
```

---

---
title: Cloudflare IP addresses
description: IP addresses used by Cloudflare for DNS zone transfers and NOTIFY messages.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

Cloudflare is updating the source IP addresses used for DNS zone transfers (AXFR/IXFR) and NOTIFY messages. You must update your allow lists before **December 1, 2026** to avoid service disruption.

# Cloudflare IP addresses

Depending on your setup ([Cloudflare as Primary](#cloudflare-as-primary) or [Cloudflare as Secondary](#cloudflare-as-secondary)), you need to configure slightly different Cloudflare IP addresses at your other DNS provider.

## Source IP addresses

Cloudflare's AXFR/IXFR zone transfer requests and NOTIFY messages originate from the following IP addresses. These need to be allowed at your other DNS servers.

```

104.30.167.163

104.30.167.173

2a09:bac0:1000:c47::/64


```

Action required: IP address migration

Since April 15, 2026, Cloudflare sends from the new IP addresses listed above and temporarily falls back to the old IP addresses if the new ones are blocked.

**On December 1, 2026, the old IP addresses will stop working.** Only the new IP addresses listed above will be used.

If you have an existing configuration, add the new IP addresses to your allow list first, verify that transfers and NOTIFY messages are working from the new addresses, and only then remove the old IP addresses.

Old source IP addresses (deprecated — removed December 1, 2026)

```

198.41.144.240/28

198.41.150.240/28

2a06:98c0:3601::/48

2a06:98c0:1401::/48


```

## Cloudflare as Primary

If you are using Cloudflare for Primary DNS — meaning that you are setting up Cloudflare to send [outgoing zone transfers](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-primary/) — you need to update the following settings at your secondary DNS provider.

### Allow range

Cloudflare's NOTIFY messages originate from the [source IP addresses](#source-ip-addresses) listed above. Allow them at your secondary DNS servers.

### Transfer IP

Cloudflare will listen to AXFR/IXFR zone transfer requests and SOA queries from your Secondary DNS server on this IP address.

```

172.65.64.6


```

## Cloudflare as Secondary

If you are using Cloudflare for Secondary DNS — meaning that you are setting up Cloudflare to receive [incoming zone transfers](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) — you need to update the following settings at your primary DNS provider.

### Allow range

Cloudflare's AXFR/IXFR zone transfer requests originate from the [source IP addresses](#source-ip-addresses) listed above. Allow them at your primary DNS servers.

### Notify IPs

Notify IPs are the IP addresses where you notify Cloudflare's Secondary DNS to initiate a pull of new zone information from your Primary DNS servers:

```

172.65.30.82

172.65.50.145

2606:4700:60:0:317:26ee:3bdf:5774

2606:4700:60:0:35a:4be3:4144:c5ee


```

### BIND server configuration

To run a BIND server as a primary, add the following statements to your zone file:

```

allow-transfer {104.30.167.163;104.30.167.173;2a09:bac0:1000:c47::/64;}

also-notify { 172.65.30.82;172.65.50.145;2606:4700:60:0:317:26ee:3bdf:5774;2606:4700:60:0:35a:4be3:4144:c5ee;}


```

Warning

If you are updating an existing BIND configuration, first add the new IP addresses alongside the old ones in your `allow-transfer` directive. Verify that zone transfers are completing successfully from the new addresses, and only then remove the old IP addresses. The old IP addresses will stop working on **December 1, 2026**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/zone-transfers/","name":"DNS Zone transfers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/zone-transfers/access-control-lists/","name":"Access Control Lists (ACLs)"}},{"@type":"ListItem","position":6,"item":{"@id":"/dns/zone-setups/zone-transfers/access-control-lists/cloudflare-ip-addresses/","name":"Cloudflare IP addresses"}}]}
```

---

---
title: Create ACL
description: Create an ACL for DNS zone transfers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Create ACL

You need to create an Access Control List (ACL) if Cloudflare is your [secondary DNS provider](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/). The ACL will specify additional NOTIFY IPs that Cloudflare should listen to.

An ACL is configured at the account level, which means that it will apply to every primary and secondary zone in your account.

* [ Dashboard ](#tab-panel-7999)
* [ API ](#tab-panel-8000)

To create a new ACL using the dashboard:

1. In the Cloudflare dashboard, go to the account **Settings** page.  
[ Go to **Configurations** ](https://dash.cloudflare.com/?to=/:account/configurations)
2. Go to **DNS Settings**.
3. Under **DNS Zone Transfers**, for **ACL**, select **Create**.
4. Enter the following information:  
   * **ACL name**: Provide a descriptive name.  
   * **IP range**: Enter a range of IPv4 or IPv6 addresses (limited to a maximum of /24 for IPv4 and /64 for IPv6).
5. Select **Create**.

To create a new ACL using the API, send a [POST](https://developers.cloudflare.com/api/resources/dns/subresources/zone%5Ftransfers/subresources/acls/methods/create/) request.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/zone-transfers/","name":"DNS Zone transfers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/zone-transfers/access-control-lists/","name":"Access Control Lists (ACLs)"}},{"@type":"ListItem","position":6,"item":{"@id":"/dns/zone-setups/zone-transfers/access-control-lists/create-new-list/","name":"Create ACL"}}]}
```

---

---
title: Cloudflare as Primary
description: Use Cloudflare as the primary DNS with zone transfers to secondaries.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare as Primary

With outgoing zone transfers, you can use Cloudflare as your primary DNS provider and configure one or more peer DNS servers as secondary DNS providers.

When you [make edits](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) to Cloudflare DNS, those DNS records will be transferred from Cloudflare to your secondary provider via zone transfer using [AXFR ↗](https://datatracker.ietf.org/doc/html/rfc5936) or [IXFR ↗](https://datatracker.ietf.org/doc/html/rfc1995)

![With Cloudflare as your primary provider in a multi-provider setup, Cloudflare periodically transfers records to your secondary DNS provider.](https://developers.cloudflare.com/_astro/cloudflare-as-primary.CS_-J48n_Z1u2wbK.webp) 

## How to

* [Set up outgoing zone transfers](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-primary/setup/)

## Availability

Outgoing zone transfers are available to Enterprise customers who are currently using Cloudflare as their [authoritative DNS provider](https://developers.cloudflare.com/dns/zone-setups/full-setup/). For more details on activation and pricing, contact your account team.

## Notes

If you use [Cloudflare Load Balancing](https://developers.cloudflare.com/load-balancing/), only proxied Load Balancer DNS records will be transferred.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/zone-transfers/","name":"DNS Zone transfers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-primary/","name":"Cloudflare as Primary"}}]}
```

---

---
title: Set up DNSSEC with Cloudflare as Primary
description: With outgoing zone transfers, you keep Cloudflare as your primary DNS provider and use one or more secondary providers for increased availability and fault tolerance.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Set up DNSSEC with Cloudflare as Primary

With [outgoing zone transfers](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-primary/), you keep Cloudflare as your primary DNS provider and use one or more secondary providers for increased availability and fault tolerance.

If you want to use DNSSEC with outgoing zone transfers, you should configure [multi-signer DNSSEC](https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/). After setting up [Cloudflare as primary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-primary/setup/), follow the steps below to enable DNSSEC.

## Before you begin

Note that:

* This process requires that your other DNS provider(s) also support multi-signer DNSSEC.
* Although you can complete a few steps via the dashboard, currently the whole process can only be completed using the API.
* Enabling **DNSSEC** and **Multi-signer DNSSEC** in [**DNS Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings) only replaces the first step below. You still have to follow the rest of this tutorial to complete the setup.

## Steps

1. Use the [Edit DNSSEC Status endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/edit/) to enable DNSSEC and activate multi-signer DNSSEC for your zone. This is done by setting `status` to `active` and `dnssec_multi_signer` to `true`, as in the following example.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Edit DNSSEC Status

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dnssec" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "status": "active",

    "dnssec_multi_signer": true

  }'


```

1. Add the ZSK(s) of your external provider(s) to Cloudflare by creating a DNSKEY record on your zone.

Terminal window

```

curl 'https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records' \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data '{

  "type": "DNSKEY",

  "name": "<ZONE_NAME>",

  "data": {

    "flags": 256,

    "protocol": 3,

    "algorithm": 13,

    "public_key": "<PUBLIC_KEY>"

  },

  "ttl": 3600

}'


```

1. Once the DNSKEY record is transferred out from Cloudflare to your secondary provider, get Cloudflare's ZSK and manually add it to the DNSKEY record.  
Currently, the ZSK is not automatically transferred out. You can use either the API or a query from one of the assigned Cloudflare nameservers to obtain it.

API example:

Terminal window

```

curl 'https://api.cloudflare.com/client/v4/zones/{zone_id}/dnssec/zsk' \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>"


```

Command line query example:

Terminal window

```

$ dig <ZONE_NAME> dnskey @<CLOUDFLARE_NAMESERVER> +noall +answer | grep 256


```

1. Add DS records to your registrar, one for each provider. You can see your Cloudflare DS record on the [**DNS Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings) page, under **DS Record**.

The nameserver settings at your registrar should include the nameservers of all providers you will be using for your multi-signer DNSSEC setup.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/zone-transfers/","name":"DNS Zone transfers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-primary/","name":"Cloudflare as Primary"}},{"@type":"ListItem","position":6,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-primary/dnssec-for-primary/","name":"Set up DNSSEC with Cloudflare as Primary"}}]}
```

---

---
title: Setup
description: With outgoing zone transfers, you can keep Cloudflare as your primary DNS provider and use one or more secondary providers for increased availability.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Setup

With [outgoing zone transfers](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-primary/), you can keep Cloudflare as your primary DNS provider and use one or more secondary providers for increased availability and fault tolerance.

## Before you begin

Make sure your account team has enabled your zone for outgoing zone transfers.

Consider the [expected behaviors](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-primary/transfer-criteria/) for different record types, and review your [existing DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) to make sure all of them have the desired **Proxy status**.

If using the API, you may also want to [locate your Zone and Account IDs](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/).

---

## 1\. Create TSIG (optional)

A Transaction Signature (TSIG) authenticates communication between a primary and secondary DNS server.

Note

The TSIG names configured at your primary and secondary DNS providers have to be exactly the same. Any differences in TSIG names will cause zone transfers to fail.

While optional, this step is highly recommended.

* [ Dashboard ](#tab-panel-8007)
* [ API ](#tab-panel-8008)

To create a TSIG using the dashboard:

1. In the Cloudflare dashboard, go to the account **Settings** page.  
[ Go to **Configurations** ](https://dash.cloudflare.com/?to=/:account/configurations)
2. Go to **DNS Settings**.
3. Under **DNS Zone Transfers**, for **TSIG**, select **Create**.
4. Enter the following information:  
   * **TSIG name**: The name of the TSIG object using domain name syntax (more details in [RFC 8945 section 4.2 ↗](https://datatracker.ietf.org/doc/html/rfc8945#section-4.2)).  
   * **Secret (optional)**: Get a shared secret to add to your third-party nameservers. If left blank, this field generates a random secret.  
   * **Algorithm**: Choose a TSIG signing algorithm.
5. Select **Create**.

To create a TSIG using the API, send a [POST](https://developers.cloudflare.com/api/resources/dns/subresources/zone%5Ftransfers/subresources/tsigs/methods/create/) request.

## 2\. Create Peer DNS Server (optional)

You only need to create a peer DNS server if you want:

* Your secondary nameservers to receive **NOTIFYs** for changes to your Cloudflare DNS records.
* A **TSIG** to sign zone transfer requests and **NOTIFYs**.

* [ Dashboard ](#tab-panel-8003)
* [ API ](#tab-panel-8004)

To create a peer using the dashboard:

1. In the Cloudflare dashboard, go to the account **Settings** page.  
[ Go to **Configurations** ](https://dash.cloudflare.com/?to=/:account/configurations)
2. Go to **DNS Settings**.
3. Under **DNS Zone Transfers**, for **Peer DNS servers**, select **Create**.
4. Enter the following information, paying particular attention to:  
   * **IP**: If configured, specifies where Cloudflare sends NOTIFY requests to.  
   * **Port**: Specifies the IP Port for the NOTIFY IP.  
   * **Enable incremental (IXFR) zone transfers**: Does not apply when you are using Cloudflare as your primary DNS provider (Cloudflare zones always accept IXFR requests).  
   * **Link an existing TSIG**: If desired, link the TSIG you [previously created](#1-create-tsig-optional).
5. Select **Create**.

To create a peer DNS server using the API, send a [POST](https://developers.cloudflare.com/api/resources/dns/subresources/zone%5Ftransfers/subresources/peers/methods/create/) request.

## 3\. Link peer to primary zone (optional)

If you previously [created a peer DNS server](#2-create-peer-dns-server-optional), you should link it to your primary zone.

Note

The maximum number of linked peers per zone is 30.

* [ Dashboard ](#tab-panel-8005)
* [ API ](#tab-panel-8006)

To link a primary zone to a peer using the dashboard:

1. In the Cloudflare dashboard, go to the **DNS Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings)
2. For **DNS Zone Transfers**, select **Manage linked peers**.
3. Select a peer.
4. Select **Save**.

To link a primary zone to a peer using the API, send a [POST](https://developers.cloudflare.com/api/resources/dns/subresources/zone%5Ftransfers/subresources/incoming/methods/create/) request with the ID of the peer you [previously created](#2-create-peer-dns-server-optional).

Multiple peers and TSIG

If you link more than one peer to a zone and at least one of them has TSIG configured, all peers are expected to also use the same TSIG.

## 4\. Update your secondary DNS provider

Your secondary DNS provider should send zone transfer requests (via AXFR or IXFR) to [this IP](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/access-control-lists/cloudflare-ip-addresses/#transfer-ip) on port 53 and from the IP address specified in your [peer configuration](#2-create-peer-dns-server-optional).

It should also have updated [Access Control Lists (ACLs)](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/access-control-lists/cloudflare-ip-addresses/#allow-range) to prevent NOTIFY messages sent from Cloudflare IP ranges from being blocked.

## 5\. Add secondary nameservers within Cloudflare

Using the information from your secondary DNS provider, [create NS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) on your zone apex listing your secondary nameservers.

By default, Cloudflare ignores NS records added to the zone apex. To modify this behavior, enable [multi-provider DNS](https://developers.cloudflare.com/dns/nameservers/nameserver-options/#multi-provider-dns).

Note

If your account [zone defaults](https://developers.cloudflare.com/dns/additional-options/dns-zone-defaults/) are already defined to have **Multi-provider DNS** enabled, this step may not be necessary.

* [ Dashboard ](#tab-panel-8009)
* [ API ](#tab-panel-8010)

1. In the Cloudflare dashboard, go to the **DNS Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings)
2. Enable **Multi-provider DNS**.

Send the following `PATCH` request replacing the placeholders with your zone ID and authentication information:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone DNS Settings Write`
* `DNS Write`

Update DNS Settings

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_settings" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "multi_provider": true

  }'


```

Note

In case you want to keep Cloudflare as the only authoritative DNS provider, do not enable multi-provider DNS. In this way, your secondary DNS is kept hidden and up-to-date with the Cloudflare primary, as a backup option for disaster recovery scenarios.

## 6\. Enable outgoing zone transfers

When you enable outgoing zone transfers, this will send a DNS NOTIFY message to your secondary DNS provider.

* [ Dashboard ](#tab-panel-8001)
* [ API ](#tab-panel-8002)

1. In the Cloudflare dashboard, go to the **DNS Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings)
2. For **Outgoing Zone Transfers**, switch the toggle to **On**.

To enable outgoing zone transfers using the API, send a [POST](https://developers.cloudflare.com/api/resources/dns/subresources/zone%5Ftransfers/subresources/outgoing/methods/enable/) request.

## 7\. Add secondary nameservers to registrar

At your registrar, add the nameservers of your secondary DNS provider.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/zone-transfers/","name":"DNS Zone transfers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-primary/","name":"Cloudflare as Primary"}},{"@type":"ListItem","position":6,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-primary/setup/","name":"Setup"}}]}
```

---

---
title: Records transfer
description: Which records transfer when Cloudflare is primary.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Records transfer

Consider the sections below to understand the expected behaviors, depending on DNS record type and proxied status.

## Proxied records

For each [proxied DNS record](https://developers.cloudflare.com/dns/proxy-status/) in your zone, Cloudflare will transfer out two `A` and two `AAAA` records.

These records correspond to the [Cloudflare IP addresses ↗](https://www.cloudflare.com/ips) used for proxying traffic.

## DNS-only CNAME records

As explained in [DNS record types](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#cname), Cloudflare uses a process called [CNAME flattening](https://developers.cloudflare.com/dns/cname-flattening/) to return the final IP address instead of the CNAME target. CNAME flattening improves performance and is also what allows you to set a CNAME record on the zone apex.

Depending on the [settings](https://developers.cloudflare.com/dns/cname-flattening/set-up-cname-flattening/) you have, when you use DNS-only CNAME records with outgoing zone transfers, you can expect the following:

* For DNS-only CNAME records on the zone apex, Cloudflare will always transfer out the flattened IP addresses.
* For DNS-only CNAME records on subdomains, Cloudflare will only transfer out flattened IP addresses if the setting [**CNAME flattening for all CNAME records**](https://developers.cloudflare.com/dns/cname-flattening/set-up-cname-flattening/#for-all-cname-records) is enabled.

Per-record CNAME flattening

For records using [per-record CNAME flattening](https://developers.cloudflare.com/dns/cname-flattening/set-up-cname-flattening/#per-record) (meaning **CNAME flattening for all CNAME records** is disabled), Cloudflare will transfer out the CNAME, not the flattened IP address.

## Records that are not transferred

The following records are not transferred out when you use Cloudflare as primary:

* [CAA records](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/)
* TXT records used for TLS certificate validation
* DNS-only [Load Balancing](https://developers.cloudflare.com/load-balancing/load-balancers/dns-records/) records

Note

Proxied Load Balancing records are transferred as explained in [Proxied records](#proxied-records).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/zone-transfers/","name":"DNS Zone transfers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-primary/","name":"Cloudflare as Primary"}},{"@type":"ListItem","position":6,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-primary/transfer-criteria/","name":"Records transfer"}}]}
```

---

---
title: Cloudflare as Secondary
description: Use Cloudflare as a secondary DNS provider.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare as Secondary

With incoming zone transfers, you can keep your primary DNS provider and use Cloudflare as a secondary DNS provider.

When you make edits in your primary DNS provider, those DNS records will be transferred from your primary DNS provider to Cloudflare via zone transfer using [AXFR ↗](https://datatracker.ietf.org/doc/html/rfc5936) or [IXFR ↗](https://datatracker.ietf.org/doc/html/rfc1995).

flowchart LR
accTitle: Cloudflare as Secondary DNS
A((Zone Admin)) --DNS record <br /> management--> B[Primary DNS <br /> provider]
B --Zone transfer--> C[Cloudflare <br /> DNS]
B & C <--DNS lookups--> D[Resolver] <--DNS lookups--> E((User))

## How to

* [Set up incoming zone transfers](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/)
* Proxy traffic through Cloudflare with [Secondary DNS Override](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/proxy-traffic/)

## Availability

Secondary DNS is only available to Enterprise customers. For more details on activation and pricing, contact your account team.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/zone-transfers/","name":"DNS Zone transfers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-secondary/","name":"Cloudflare as Secondary"}}]}
```

---

---
title: Alerts
description: Set up alerts for secondary DNS zone transfer events.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Alerts

You can configure alerts to receive notifications for changes in your secondary DNS.

Secondary DNS all Primaries Failing

**Who is it for?**

Enterprise customers who have at least one secondary zone in their account and want to receive a notification if all of their primary nameservers are failing.

**Other options / filters**

None.

**Included with**

Purchase of Secondary DNS

**What should you do if you receive one?**

1. Confirm that your primary nameservers are up and running.
2. Confirm that the [Access Control Lists (ACLs)](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/access-control-lists/cloudflare-ip-addresses/) on your primary nameservers are configured correctly.
3. Confirm that your primary nameservers are configured correctly in your Cloudflare account (correct IP, port, TSIG).

Secondary DNS Primaries Failing

**Who is it for?**

Enterprise customers who have at least one secondary zone and want to receive a notification if at least one of their primary nameservers is failing while transfers from at least one other primary are still successful.

**Other options / filters**

None.

**Included with**

Purchase of Secondary DNS.

**What should you do if you receive one?**

1. Confirm that your primary nameservers are up and running.
2. Confirm that the [Access Control Lists (ACLs)](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/access-control-lists/cloudflare-ip-addresses/) on your primary nameservers are configured correctly.
3. Confirm that your primary nameservers are configured correctly in your Cloudflare account (correct IP, port, TSIG).

Secondary DNS Successfully Updated

**Who is it for?**

Enterprise customers who have at least one secondary zone in their account and want to receive a notification on successful zone transfers.

**Other options / filters**

None.

**Included with**

Purchase of Secondary DNS.

**What should you do if you receive one?**

No action needed. Everything is working correctly.

Secondary DNS Warning

**Who is it for?**

Customers who are using Cloudflare for Secondary DNS and want to receive notifications about warnings issued by the transferred zone.

**Other options / filters**

None.

**Included with**

Enterprise plans.

**What should you do if you receive one?**

Actions for failure notifications will depend on the type of failure.

Refer to [Cloudflare Notifications](https://developers.cloudflare.com/notifications/get-started/) for more information on how to set up an alert.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/zone-transfers/","name":"DNS Zone transfers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-secondary/","name":"Cloudflare as Secondary"}},{"@type":"ListItem","position":6,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-secondary/alerts/","name":"Alerts"}}]}
```

---

---
title: DNSSEC options
description: DNSSEC options for secondary DNS zones.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNSSEC options

[DNS Security Extensions (DNSSEC) ↗](https://www.cloudflare.com/learning/dns/dns-security/) increase security by adding cryptographic signatures to DNS records. When you use multiple providers and Cloudflare is secondary, you have a few options to enable DNSSEC for records served by Cloudflare.

* **[Multi-signer DNSSEC](https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/setup/)**: Both Cloudflare and your primary DNS provider know the signing keys of each other and perform their own live-signing of DNS records, in accordance with [RFC 8901 ↗](https://www.rfc-editor.org/rfc/rfc8901.html).
* **[Live signing](#set-up-live-signing-dnssec)**: If your domain is not delegated to your primary provider's nameservers and Cloudflare secondary nameservers are the only nameservers authoritatively responding to DNS queries (hidden primary setup), you can choose this option to allow Cloudflare to perform live-signing of your DNS records.
* **[Pre-signed](#set-up-pre-signed-dnssec)**: Your primary DNS provider signs records and transfers out the signatures. Cloudflare then serves these records and signatures as is, without doing any signing. By default, Cloudflare uses [NSEC records ↗](https://www.cloudflare.com/dns/dnssec/how-dnssec-works/) and not NSEC3 - refer to [NSEC3 support](https://developers.cloudflare.com/dns/dnssec/enable-nsec3/) if needed. Also, Pre-signed DNSSEC does not support [Secondary DNS Overrides](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/proxy-traffic/) nor [Load Balancing](https://developers.cloudflare.com/load-balancing/).

---

## Set up multi-signer DNSSEC

Refer to [Set up multi-signer DNSSEC](https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/setup/) and follow the instructions, considering the note about Cloudflare as Secondary.

---

## Set up live signing DNSSEC

If you use Cloudflare secondary nameservers as the only nameservers authoritatively responding to DNS queries (hidden primary setup), you can enable live signing DNSSEC to have Cloudflare sign the records for your zone.

In this setup, DNSSEC on your primary DNS provider does not need to be enabled.

* [ Dashboard ](#tab-panel-8013)
* [ API ](#tab-panel-8014)

1. In the Cloudflare dashboard, go to the **DNS Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings)
2. Under **DNSSEC with Secondary DNS** select **Live signing**. You will then have access to several necessary values to create a **DS** record at your registrar.
3. Add the **DS** record to your registrar. If Algorithm 13 - Cloudflare's preferred cipher choice - is not listed by your registrar, it may also be called _ECDSA Curve P-256 with SHA-256_.  
Provider-specific DNSSEC instructions  
This is not an exhaustive list, but the following links may be helpful:  
   * [DNSimple ↗](https://support.dnsimple.com/articles/cloudflare-ds-record/)  
   * [Domaindiscount24 ↗](https://support.domaindiscount24.com/hc/articles/4409759478161)  
   * [DreamHost ↗](https://help.dreamhost.com/hc/en-us/articles/219539467)  
   * [Dynadot ↗](https://www.dynadot.com/help/question/set-DNSSEC)  
   * [Enom ↗](https://support.enom.com/support/solutions/articles/201000065386)  
   * [Gandi ↗](https://docs.gandi.net/en/domain%5Fnames/advanced%5Fusers/dnssec.html)  
   * [GoDaddy ↗](https://www.godaddy.com/help/add-a-ds-record-23865)  
   * [Hostinger ↗](https://www.hostinger.com/support/3667267-how-to-use-dnssec-records-at-hostinger/)  
   * [Hover ↗](https://support.hover.com/support/solutions/articles/201000064716)  
   * [Infomaniak ↗](https://faq.infomaniak.com/2187)  
   * [InMotion Hosting ↗](https://www.inmotionhosting.com/support/edu/cpanel/enable-dnssec-cloudflare/)  
   * [INWX ↗](https://kb.inwx.com/en-us/3-nameserver/131)  
   * [Joker.com ↗](https://joker.com/faq/books/jokercom-faq-en/page/dnssec)  
   * [Name.com ↗](https://www.name.com/support/articles/205439058-managing-dnssec)  
   * [Namecheap ↗](https://www.namecheap.com/support/knowledgebase/article.aspx/9722/2232/managing-dnssec-for-domains-pointed-to-custom-dns/)  
   * [NameISP ↗](https://support.nameisp.com/knowledgebase/dns)  
   * [Namesilo ↗](https://www.namesilo.com/support/v2/articles/domain-manager/ds-records)  
   * [OVH ↗](https://help.ovhcloud.com/csm/en-dns-secure-domain-dnssec?id=kb%5Farticle%5Fview&sysparm%5Farticle=KB0051637)  
   * [Squarespace ↗](https://support.squarespace.com/hc/articles/4404183898125-Nameservers-and-DNSSEC-for-Squarespace-managed-domains#toc-dnssec)  
   * [Registro.br ↗](https://registro.br/tecnologia/dnssec/?secao=tutoriais-dns)  
   * [Porkbun ↗](https://kb.porkbun.com/article/93-how-to-install-dnssec) (do not fill out **keyData**)  
   * [TransIP ↗](https://www.transip.eu/knowledgebase/150-secure-domains-custom-nameservers-dnssec/)

1. Use the [Edit DNSSEC Status endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/edit/) and set a `status` of `active` for your zone.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Edit DNSSEC Status

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dnssec" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "status": "active"

  }'


```

1. Use the [DNSSEC Details endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/get/) to get the necessary values to create a **DS** record at your registrar.
2. Add the **DS** record to your registrar. If Algorithm 13 - Cloudflare's preferred cipher choice - is not listed by your registrar, it may also be called _ECDSA Curve P-256 with SHA-256_.  
Provider-specific DNSSEC instructions  
This is not an exhaustive list, but the following links may be helpful:  
   * [DNSimple ↗](https://support.dnsimple.com/articles/cloudflare-ds-record/)  
   * [Domaindiscount24 ↗](https://support.domaindiscount24.com/hc/articles/4409759478161)  
   * [DreamHost ↗](https://help.dreamhost.com/hc/en-us/articles/219539467)  
   * [Dynadot ↗](https://www.dynadot.com/help/question/set-DNSSEC)  
   * [Enom ↗](https://support.enom.com/support/solutions/articles/201000065386)  
   * [Gandi ↗](https://docs.gandi.net/en/domain%5Fnames/advanced%5Fusers/dnssec.html)  
   * [GoDaddy ↗](https://www.godaddy.com/help/add-a-ds-record-23865)  
   * [Hostinger ↗](https://www.hostinger.com/support/3667267-how-to-use-dnssec-records-at-hostinger/)  
   * [Hover ↗](https://support.hover.com/support/solutions/articles/201000064716)  
   * [Infomaniak ↗](https://faq.infomaniak.com/2187)  
   * [InMotion Hosting ↗](https://www.inmotionhosting.com/support/edu/cpanel/enable-dnssec-cloudflare/)  
   * [INWX ↗](https://kb.inwx.com/en-us/3-nameserver/131)  
   * [Joker.com ↗](https://joker.com/faq/books/jokercom-faq-en/page/dnssec)  
   * [Name.com ↗](https://www.name.com/support/articles/205439058-managing-dnssec)  
   * [Namecheap ↗](https://www.namecheap.com/support/knowledgebase/article.aspx/9722/2232/managing-dnssec-for-domains-pointed-to-custom-dns/)  
   * [NameISP ↗](https://support.nameisp.com/knowledgebase/dns)  
   * [Namesilo ↗](https://www.namesilo.com/support/v2/articles/domain-manager/ds-records)  
   * [OVH ↗](https://help.ovhcloud.com/csm/en-dns-secure-domain-dnssec?id=kb%5Farticle%5Fview&sysparm%5Farticle=KB0051637)  
   * [Squarespace ↗](https://support.squarespace.com/hc/articles/4404183898125-Nameservers-and-DNSSEC-for-Squarespace-managed-domains#toc-dnssec)  
   * [Registro.br ↗](https://registro.br/tecnologia/dnssec/?secao=tutoriais-dns)  
   * [Porkbun ↗](https://kb.porkbun.com/article/93-how-to-install-dnssec) (do not fill out **keyData**)  
   * [TransIP ↗](https://www.transip.eu/knowledgebase/150-secure-domains-custom-nameservers-dnssec/)

---

## Set up pre-signed DNSSEC

### Prerequisites

* Your secondary zone in Cloudflare already exists and zone transfers from your primary DNS provider are working correctly.
* You have considered whether your primary DNS provider uses NSEC or NSEC3, and have enabled [NSEC3 support](https://developers.cloudflare.com/dns/dnssec/enable-nsec3/) if needed.
* Your primary DNS provider transfers out DNSSEC related records, such as RRSIG, DNSKEY, and NSEC.

### Steps

1. Enable DNSSEC at your primary DNS provider.
2. Enable DNSSEC for your zone at Cloudflare, using either the Dashboard or the API.

Warning

Pre-signed DNSSEC does not support [Secondary DNS Overrides](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/proxy-traffic/) nor [Load Balancing](https://developers.cloudflare.com/load-balancing/). Once you enable pre-signed DNSSEC, Cloudflare will treat all your DNS records as DNS-only.

* [ Dashboard ](#tab-panel-8011)
* [ API ](#tab-panel-8012)

1. In the Cloudflare dashboard, go to the **DNS Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings)
2. Under **DNSSEC with Secondary DNS** select **Pre-signed**.

Use the [Edit DNSSEC Status endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/edit/) and set the `dnssec_presigned` value to `true`.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Edit DNSSEC Status

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dnssec" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "dnssec_presigned": true

  }'


```

1. Make sure Cloudflare nameservers are added at your registrar. You can see your Cloudflare nameservers on the dashboard by going to the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page.
2. Make sure there is a DS record added at your registrar. The DS record is obtained from your primary DNS provider (the signer of the zone) and is what indicates to DNS resolvers that your zone has DNSSEC enabled.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/zone-transfers/","name":"DNS Zone transfers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-secondary/","name":"Cloudflare as Secondary"}},{"@type":"ListItem","position":6,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-secondary/dnssec-for-secondary/","name":"DNSSEC options"}}]}
```

---

---
title: Proxy traffic
description: Proxy traffic through Cloudflare on secondary zones.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Proxy traffic

When you set up [incoming zone transfers](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/) on a secondary zone, you cannot enable the proxy on any transferred DNS records by default.

With Secondary DNS override, you can use Cloudflare as your secondary DNS provider but still get the [performance and security benefits](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/#cloudflare-as-a-reverse-proxy) of Cloudflare's proxy. Additionally it lets you override any A and AAAA records on your zone apex with a CNAME record.

Note

Only A, AAAA, and CNAME records can be proxied.

## Prerequisites

Before you set up Secondary DNS override, make sure that you have:

* [Set up a secondary DNS zone](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/) and confirmed your DNS records are transferred correctly.
* Set your [DNSSEC with Secondary DNS ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings/) option to either **Unsigned** or **Live Signing**. If set to [Pre-signed](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/dnssec-for-secondary/#set-up-pre-signed-dnssec), Cloudflare will treat all your DNS records as unproxied (DNS only).
* Removed all nameservers from your registrar except for those provided by Cloudflare (highly recommended).  
Warning  
If you use Secondary DNS override and keep other nameservers at your registrar, DNS responses will be inconsistent across DNS providers, which goes against [official standards ↗](https://www.iana.org/help/nameserver-requirements).

## Set up Secondary DNS override

* [ Dashboard ](#tab-panel-8015)
* [ API ](#tab-panel-8016)

1. In the Cloudflare dashboard, go to the **DNS Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings)
2. Enable **Secondary DNS override**.
3. On the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page, for specific A, AAAA, or CNAME records, select the grey cloud icon to set their **Proxy status** to **Proxied**.

1. To enable Secondary DNS override on a zone, use the following PATCH request:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone DNS Settings Write`
* `DNS Write`

Update DNS Settings

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_settings" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "secondary_overrides": true

  }'


```

1. For specific A, AAAA, or CNAME records, send a [POST](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) request with the `proxied` status as `true`.  
   * Make sure the added record has the same name as the transferred record you intend to proxy. Cloudflare only looks at the name and the proxy status, so the record content does not matter.

Zone transfers interaction

Zone transfers from the primary (including content or TTL changes) do not change the proxy status of records you set to proxied. The override persists until the record is deleted on the primary.

## Proxied A and AAAA records

After proxying (orange clouding) a Secondary DNS record, any additional records under that hostname transferred from the primary DNS provider are automatically proxied. This applies to all A and AAAA records under that domain.

## CNAME record on the zone apex

You can also add a CNAME record on the zone apex (supported through [CNAME Flattening](https://developers.cloudflare.com/dns/cname-flattening/)) and either proxy that record or keep it on DNS Only.

Once you create a CNAME record at the apex, existing A or AAAA records on the zone apex will be deactivated. You can view those deactivated records by clicking **View Inactive Records**. To re-activate the A or AAAA records at the root, remove the CNAME record.

## Verify that your records are proxied

Query DNS at your assigned Secondary DNS nameserver to confirm the DNS response Cloudflare returns. Records proxied by Cloudflare return [Cloudflare IPs ↗](https://www.cloudflare.com/ips/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/zone-transfers/","name":"DNS Zone transfers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-secondary/","name":"Cloudflare as Secondary"}},{"@type":"ListItem","position":6,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-secondary/proxy-traffic/","name":"Proxy traffic"}}]}
```

---

---
title: Setup
description: With incoming zone transfers, you can keep your primary DNS provider and use Cloudflare as a secondary DNS provider.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Setup

With [incoming zone transfers](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/), you can keep your primary DNS provider and use Cloudflare as a secondary DNS provider.

Normal incoming zone transfers only provide DNS resolution. If you also want your traffic to benefit from Cloudflare's performance and security features, you need to [set up Secondary DNS Override](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/proxy-traffic/).

  
## Before you begin

* You should already have a registered domain, set up with your primary DNS provider.
* Review the available options and plan for how you will use [DNSSEC with Cloudflare as secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/dnssec-for-secondary/).
* Make sure you have completed the following tasks at your primary DNS provider and at Cloudflare.

### At your primary DNS provider

Your primary DNS provider should allow traffic from the IP address and port specified in your [peer server configuration](#2-create-peer-server).

It should also have updated [Access Control Lists (ACLs)](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/access-control-lists/cloudflare-ip-addresses/#cloudflare-as-secondary) to prevent zone transfers from being blocked.

We strongly recommend configuring [DNS NOTIFY ↗](https://datatracker.ietf.org/doc/html/rfc1996) at your primary DNS provider to ensure your secondary zone on Cloudflare is updated with the most recent changes as quickly as possible. In order to do so, set up [Cloudflare NOTIFY IPs](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/access-control-lists/cloudflare-ip-addresses/#notify-ips) at your primary DNS provider.

You will also need the following information from your Primary DNS provider:

* **Primary IP address**: The IP address that Cloudflare sends zone transfer requests to (via AXFR or IXFR).
* **Zone transfer type**: Will zone transfers be full (AXFR) or incremental (IXFR)?
* **TSIG name** (optional): A descriptive name of the TSIG following domain name syntax ([RFC 8945 section 4.2 ↗](https://datatracker.ietf.org/doc/html/rfc8945#section-4.2)).  
Note  
The TSIG names configured at your primary and secondary DNS providers have to be exactly the same. Any differences in TSIG names will cause zone transfers to fail.
* **TSIG secret** (optional): The secret string used to authenticate zone transfers.
* **TSIG algorithm** (optional): The algorithm used to authenticate zone transfers.

### At Cloudflare

Make sure your account team has enabled your zone for Secondary DNS.

Get the following values from your Cloudflare account:

* [Account ID](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/)
* [Zone ID](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/)
* [Nameserver names](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/#31-get-nameserver-names), which should have **secondary** in the name.

---

## 1\. Create TSIG (optional)

A Transaction Signature (TSIG) authenticates communication between a primary and secondary DNS server.

Note

The TSIG names configured at your primary and secondary DNS providers have to be exactly the same. Any differences in TSIG names will cause zone transfers to fail.

While optional, this step is highly recommended.

* [ Dashboard ](#tab-panel-8019)
* [ API ](#tab-panel-8020)

To create a TSIG using the dashboard:

1. In the Cloudflare dashboard, go to the account **Settings** page.  
[ Go to **Configurations** ](https://dash.cloudflare.com/?to=/:account/configurations)
2. Go to **DNS Settings**.
3. Under **DNS Zone Transfers**, for **TSIG**, select **Create**.
4. Enter the following information:  
   * **TSIG name**: The name of the TSIG object using domain name syntax (more details in [RFC 8945 section 4.2 ↗](https://datatracker.ietf.org/doc/html/rfc8945#section-4.2)).  
   * **Secret (optional)**: Get a shared secret to add to your third-party nameservers. If left blank, this field generates a random secret.  
   * **Algorithm**: Choose a TSIG signing algorithm.
5. Select **Create**.

To create a TSIG using the API, send a [POST](https://developers.cloudflare.com/api/resources/dns/subresources/zone%5Ftransfers/subresources/tsigs/methods/create/) request.

## 2\. Create Peer Server

* [ Dashboard ](#tab-panel-8017)
* [ API ](#tab-panel-8018)

To create a peer server using the dashboard:

1. In the Cloudflare dashboard, go to the account **Settings** page.  
[ Go to **Configurations** ](https://dash.cloudflare.com/?to=/:account/configurations)
2. Go to **DNS Settings**.
3. Under **DNS Zone Transfers**, for **Peer DNS servers**, select **Create**.
4. Enter the following information, paying particular attention to:  
   * **IP**: Specifies where Cloudflare sends transfer requests to.  
   * **Port**: Specifies the IP Port for the transfer IP.  
   * **Enable incremental (IXFR) zone transfers**: Specifies if Cloudflare sends IXFR requests in addition to the default AXFR requests.  
   * **Link an existing TSIG**: If desired, link the TSIG you [previously created](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/#1-create-tsig-optional).
5. Select **Create**.

To create a peer DNS server using the API, send a [POST request](https://developers.cloudflare.com/api/resources/dns/subresources/zone%5Ftransfers/subresources/peers/).

## 3\. Create the Secondary Zone

* [ Dashboard ](#tab-panel-8021)
* [ API ](#tab-panel-8022)

To create a secondary zone using the dashboard:

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/login) and select your account.
2. Select **Onboard a domain**.
3. Enter your zone name and choose **Secondary DNS** (if this option is not available, contact your account team).
4. Select **Continue**.
5. Select your plan type.
6. Choose a value for **Zone refresh**, which controls the number of seconds between zone updates from your primary DNS server.  
Warning  
Cloudflare will not use the REFRESH value inside the SOA record that is served by your primary provider. Instead the value of zone refresh configured for your secondary zone on Cloudflare will be used to determine the interval after which the SOA serial of the primary zone will be checked for changes.
7. Select the peer server you [previously created](#2-create-peer-server). If needed, you can link more than one peer server to a zone.  
Note  
The maximum number of linked peers per zone is 30.
8. Select **Continue**.
9. Review the list of transferred records and select **Continue**.  
Note  
If no records appear, you may have misconfigured the TSIG or the IP address of the peer server or the [Access Control List](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/access-control-lists/cloudflare-ip-addresses/#cloudflare-as-secondary) was improperly configured at your primary DNS provider.
10. Select **Initiate zone transfer**.

To create a secondary zone using the API, send a [POST](https://developers.cloudflare.com/api/resources/dns/subresources/zone%5Ftransfers/subresources/incoming/methods/create/) request with the `type` parameter set to `"secondary"`.

## 4\. Update registrar

At your registrar, add the secondary nameservers [specified in the Cloudflare dashboard](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/#31-get-nameserver-names). Do not remove your primary DNS provider's nameservers.

When you have added the Cloudflare nameservers, go into your new secondary zone and select **Done, check nameservers**.

## 5\. Create notifications (optional)

To increase the reliability of your incoming zone transfers, [set up notifications](https://developers.cloudflare.com/notifications/get-started/#create-a-notification) to be notified when your primaries are failing, when records are updated, [and more](https://developers.cloudflare.com/notifications/notification-available/#dns).

## 6\. Proxy traffic through Cloudflare (optional)

Normal incoming zone transfers only provide DNS resolution. If you also want your traffic to benefit from Cloudflare's performance and security features, you need to [set up Secondary DNS Override](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/proxy-traffic/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/zone-transfers/","name":"DNS Zone transfers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-secondary/","name":"Cloudflare as Secondary"}},{"@type":"ListItem","position":6,"item":{"@id":"/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/","name":"Setup"}}]}
```

---

---
title: Troubleshooting
description: Learn how to troubleshoot issues with secondary nameservers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

When [updating your registrar](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/setup/#4-update-registrar) with the Cloudflare secondary nameservers (`nsXXXX.secondary.cloudflare.com`), you get an error.

Note

The exact error message depends on the system. Some examples would be: `Entity reference not found`,` Authorization error`, `Unable to create foreign nameserver`.

Upon contacting your registrar, their services confirm that the Cloudflare nameservers cannot be added at this time.

---

## Cause

This issue may arise when one of the Cloudflare nameservers used for secondary setup is removed from the Verisign side.

---

## Solution

The Cloudflare engineering team needs to be engaged [through Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) to make sure the nameserver gets registered again manually at Verisign.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/zone-setups/","name":"DNS setups"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/zone-setups/zone-transfers/","name":"DNS Zone transfers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/zone-setups/zone-transfers/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: Foundation DNS
description: Enterprise DNS with advanced nameservers and DNSSEC controls.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Foundation DNS

Foundation DNS is the Cloudflare DNS offering for enterprise customers.

With Foundation DNS, you get access to increased reliability, security, and insights. Features include the following:

* [Advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/advanced-nameservers/) that provide:  
   * Strategically distributed IPs to enhance resiliency  
   * Reduced exposure to incidents or software regression  
   * More consistent nameserver assignment
* [DNSSEC keys](https://developers.cloudflare.com/dns/foundation-dns/dnssec-keys/) unique to your account
* Additional DNS settings, including:  
   * [Zone defaults](https://developers.cloudflare.com/dns/additional-options/dns-zone-defaults/)  
   * [Account custom nameservers](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/account-custom-nameservers/)  
   * Custom [SOA record](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#soa) and [Nameserver TTL](https://developers.cloudflare.com/dns/nameservers/nameserver-options/#nameserver-ttl)

## Availability

Foundation DNS is only available to Enterprise customers.

Note

Both advanced nameservers and unique ZSK/KSK are opt-in configurations. Refer to [set up advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/setup/) and [DNSSEC keys](https://developers.cloudflare.com/dns/foundation-dns/dnssec-keys/) for details.

## Related resources

* [Release blog post ↗](https://blog.cloudflare.com/foundation-dns-launch)
* [Product page ↗](https://www.cloudflare.com/dns/foundation-dns/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/foundation-dns/","name":"Foundation DNS"}}]}
```

---

---
title: Advanced nameservers
description: Advanced nameserver features for Foundation DNS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Advanced nameservers

Advanced nameservers included with [Foundation DNS](https://developers.cloudflare.com/dns/foundation-dns/) offer improved resiliency and more consistent nameserver assignment.

Consider the sections below for details about advanced nameservers, and refer to [Set up advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/setup/) to learn how to enable this feature.

Note

The advantages that come with Foundation DNS [advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/advanced-nameservers/) are currently not available for [custom nameservers](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/). Make sure you only use one at a time.

Also, [some behaviors are different](https://developers.cloudflare.com/dns/foundation-dns/setup/#differences-from-standard-nameservers) when compared to standard nameservers.

## Anycast network groups

To increase resiliency, the advertisement of advanced nameserver IPs is organized into three anycast network groups.

Two groups consist of IPs advertised from geographically distributed data centers, and a third group consists of IPs advertised from all data centers in the Cloudflare network.

United Kingdom example

| IPs           | Group | Data centers                      |
| ------------- | ----- | --------------------------------- |
| 108.162.198.1 | A     | London and Edinburgh              |
| 172.64.40.1   | B     | Manchester                        |
| 162.159.60.1  | C     | Manchester, London, and Edinburgh |

In DNS resolution, a resolver eventually acquires a list of all IPs where authoritative nameservers for a domain can be reached, and will then usually prefer the IP with the best resolution performance.

When, instead of advertising all IPs in all data centers, this group logic is applied, resiliency is improved because, if one of the data centers experiences a localized issue, the resolver can fall back to an IP advertised by the next closest data center. The third group adds another layer of redundancy, further enhancing resiliency.

Refer to [our blog post ↗](https://blog.cloudflare.com/foundation-dns-launch) for an in-depth explanation of the distributed groups logic.

Note

The IPs assigned to each nameserver are static, meaning they will not change without notification.

## Dedicated release process

Zones using advanced nameservers are less exposed to incidents or software regression.

The dedicated release process means that only changes that have been in production for a while will reach advanced nameservers.

## Nameservers hosting and assignment

While standard Cloudflare nameservers are hosted under `ns.cloudflare.com` or `secondary.cloudflare.com`, advanced nameservers use different domains:

* `foundationdns.com`
* `foundationdns.net`
* `foundationdns.org`

Using the different TLDs (`.com`, `.net`, and `.org`) and making these available only to enterprise accounts allows for better predictability and consistency in nameserver assignment.

There should also be less conflicts when guaranteeing that directly descending zones do not have the same nameserver set.

Descending zones example

Consider the domain `example.com`, and subdomains `abc.example.com` and `123.example.com`:

* `abc.example.com` and `123.example.com` directly descend from `example.com` and cannot have the same nameservers as `example.com`.
* `abc.example.com` and `123.example.com` are sibling domains and can have the same nameservers.
* `new.abc.example.com` directly descends from both `abc.example.com` and `example.com`, and cannot have the same nameservers as them, but can have the same nameservers as `123.example.com`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/foundation-dns/","name":"Foundation DNS"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/foundation-dns/advanced-nameservers/","name":"Advanced nameservers"}}]}
```

---

---
title: DNSSEC keys
description: DNSSEC key management for Foundation DNS zones.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNSSEC keys

With [Foundation DNS](https://developers.cloudflare.com/dns/foundation-dns/), you can request that the ZSK/KSK pair that is used for [DNSSEC](https://developers.cloudflare.com/dns/dnssec/) is unique to your Cloudflare account. To opt in to this feature, contact your account team.

All zones within your Cloudflare account - regardless of using [standard](https://developers.cloudflare.com/dns/nameservers/#standard-nameservers) or [advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/advanced-nameservers/) \- will use the dedicated Zone Signing Key (ZSK) and Key Signing Key (KSK) for DNSSEC. These keys are set at the account level.

## Further reading

For more background information, refer to [How DNSSEC works ↗](https://www.cloudflare.com/learning/dns/dnssec/how-dnssec-works/).

For details about DNSSEC settings at Cloudflare, refer to the [DNSSEC documentation](https://developers.cloudflare.com/dns/dnssec/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/foundation-dns/","name":"Foundation DNS"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/foundation-dns/dnssec-keys/","name":"DNSSEC keys"}}]}
```

---

---
title: Set up advanced nameservers
description: Set up advanced nameservers for your Foundation DNS zone.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Set up advanced nameservers

Advanced nameservers included with [Foundation DNS](https://developers.cloudflare.com/dns/foundation-dns/) are an opt-in configuration.

Note

After enabling advanced nameservers, standard nameservers still respond to DNS queries.

## Before you begin

Before opting in for advanced nameservers, consider the following:

* The advantages that come with Foundation DNS [advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/advanced-nameservers/) are currently not available for [custom nameservers](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/). Make sure you only use one at a time.

### Differences from standard nameservers

Some behaviors are different from standard Cloudflare nameservers:

* Wildcard records are still supported but, with advanced nameservers, a wildcard record (`*.example.com`) will not apply to a subdomain that is an empty non-terminal. An empty non-terminal is a node in the DNS tree that has no records associated with it but has descendants that do, as exemplified below. This behavior is in compliance with [RFC 4592 ↗](https://www.rfc-editor.org/rfc/rfc4592.html), which defines the role of empty non-terminals in wildcard resolution.

Example

DNS management for **example.com**

| **Type** | **Name** | **Content** |
| -------- | -------- | ----------- |
| A        | \*       | 192.0.2.1   |
| A        | a.b      | 192.0.2.5   |

In this example, `a.b.example.com` is a descendant of `b.example.com`, and `b.example.com` is an empty non-terminal. This means that the wildcard `*.example.com` will not apply to `b.example.com`.

* Subdomain delegation: once a subdomain is delegated via NS records, Cloudflare will not serve any other records (such as A, TXT, or CNAME) on that subdomain from the parent zone, even if those records exist.

Example

DNS management for **example.com**

| **Type** | **Name** | **Content**                        |
| -------- | -------- | ---------------------------------- |
| NS       | www      | ns1.externalhost.com               |
| NS       | www      | ns2.externalhost.com               |
| TXT      | www      | "5bb16e6b5a444eedb48ace40c471bcc9" |
| A        | www      | 192.0.2.1                          |

In this example, the TXT record and the A record for `www.example.com` will not be served.

## Enable on a zone

To enable advanced nameservers on an existing zone:

1. Opt for advanced nameservers on your zone:  
   * [ Dashboard ](#tab-panel-7929)  
   * [ API ](#tab-panel-7930)  
   1. In the Cloudflare dashboard, go to the **DNS Records** page.  
   [ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)  
   2. In the **Cloudflare nameservers** card, enable **Advanced nameservers**.  
   3. After you refresh the page, the card will display the values for your advanced nameservers `NS` records.  
Use the [Update DNS Settings](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/methods/edit/) endpoint to send a PATCH request like the following:  
Required API token permissions  
At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:  
   * `Zone DNS Settings Write`  
   * `DNS Write`  
Update DNS Settings  
```  
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_settings" \  
  --request PATCH \  
  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \  
  --json '{  
    "foundation_dns": true  
  }'  
```  
The response body will contain your assigned nameservers in the `nameservers` object. You will use these nameservers in the next step.
2. Update the authoritative nameservers at your registrar. This step depends on whether you are using [Cloudflare Registrar](https://developers.cloudflare.com/registrar/):  
   * If you are using Cloudflare Registrar, [contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) to have your nameservers updated.  
   * If you are using a different registrar or if your zone is delegated, [manually update your nameservers](https://developers.cloudflare.com/dns/nameservers/update-nameservers/#specific-processes).  
   Warning  
   Make sure the values for your assigned nameservers are copied exactly.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/foundation-dns/","name":"Foundation DNS"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/foundation-dns/setup/","name":"Set up advanced nameservers"}}]}
```

---

---
title: Nameservers
description: Manage Cloudflare nameservers for your zones.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Nameservers

Nameservers are DNS servers that answer DNS queries about the domains they are authoritative for. When a visitor types your domain into a browser, the [DNS resolution process ↗](https://www.cloudflare.com/learning/dns/what-is-dns/) passes through several server types and eventually reaches the authoritative nameservers for the final answer.

In the context of Cloudflare DNS, nameservers refer to authoritative nameservers — the servers that hold the definitive DNS records for your domain and provide the final response in DNS resolution. When a nameserver is authoritative for `example.com`, DNS resolvers will consider responses from this nameserver when a user tries to access `example.com`.

Note

The IPs assigned to each nameserver are static, meaning they will not change without notification.

## Authoritative nameservers offering

Within Cloudflare, and depending on your plan, you can choose between using Cloudflare-branded nameservers or setting up your own custom nameservers. The names for Cloudflare-branded nameservers are automatically assigned and cannot be changed.

Regardless of the type you choose, for these nameservers to be authoritative for your domain, you need to [update your domain nameservers](https://developers.cloudflare.com/dns/nameservers/update-nameservers/), typically where you registered your domain. Updating your nameservers is required to activate your domain on Cloudflare and use most of Cloudflare's [application services](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/), such as proxying, caching, and security features.

Cloudflare Registrar

If you acquired your domain from [Cloudflare Registrar](https://developers.cloudflare.com/registrar/), your domain already uses Cloudflare nameservers, automatically protecting and speeding up your content or services. If you need to update your nameservers to use a different DNS provider, you will have to [transfer your domain from Cloudflare](https://developers.cloudflare.com/registrar/account-options/transfer-out-from-cloudflare/).

### Standard nameservers

Unless your account has a specific [DNS zone defaults](https://developers.cloudflare.com/dns/additional-options/dns-zone-defaults/) configuration, when you add a domain on a [primary (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/) or [secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) DNS setup, Cloudflare automatically assigns two standard nameservers for your zone.

Standard nameservers are hosted on `ns.cloudflare.com` and follow the pattern `<proper_name>.ns.cloudflare.com`.

To know the reason behind these nameserver names, refer to [our blog ↗](https://blog.cloudflare.com/whats-the-story-behind-the-names-of-cloudflares-name-servers/).

### Advanced nameservers

Enterprise accounts on [Foundation DNS](https://developers.cloudflare.com/dns/foundation-dns/) have access to advanced nameservers.

[Advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/advanced-nameservers/) are hosted on `foundationdns.com`, `foundationdns.net`, and `foundationdns.org`.

Each zone that uses advanced nameservers is assigned a set of three nameservers names: `<color>.foundationdns.com`, `<color>.foundationdns.net`, and `<color>.foundationdns.org`.

### Custom nameservers

With [custom nameservers](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/), your nameservers are hosted on your own domain (or domains) and, in this sense, are not Cloudflare branded.

You provide fully qualified domain names — complete domain names like `ns1.example.com` — for your nameservers, and Cloudflare assigns one IPv4 and one IPv6 address to each.

Warning

The advantages that come with Foundation DNS [advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/advanced-nameservers/) are currently not available for [custom nameservers](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/). Make sure you only use one at a time.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/nameservers/","name":"Nameservers"}}]}
```

---

---
title: Advanced nameservers
description: Advanced nameserver features for Foundation DNS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Advanced nameservers

Advanced nameservers included with [Foundation DNS](https://developers.cloudflare.com/dns/foundation-dns/) offer improved resiliency and more consistent nameserver assignment.

Consider the sections below for details about advanced nameservers, and refer to [Set up advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/setup/) to learn how to enable this feature.

Note

The advantages that come with Foundation DNS [advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/advanced-nameservers/) are currently not available for [custom nameservers](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/). Make sure you only use one at a time.

Also, [some behaviors are different](https://developers.cloudflare.com/dns/foundation-dns/setup/#differences-from-standard-nameservers) when compared to standard nameservers.

## Anycast network groups

To increase resiliency, the advertisement of advanced nameserver IPs is organized into three anycast network groups.

Two groups consist of IPs advertised from geographically distributed data centers, and a third group consists of IPs advertised from all data centers in the Cloudflare network.

United Kingdom example

| IPs           | Group | Data centers                      |
| ------------- | ----- | --------------------------------- |
| 108.162.198.1 | A     | London and Edinburgh              |
| 172.64.40.1   | B     | Manchester                        |
| 162.159.60.1  | C     | Manchester, London, and Edinburgh |

In DNS resolution, a resolver eventually acquires a list of all IPs where authoritative nameservers for a domain can be reached, and will then usually prefer the IP with the best resolution performance.

When, instead of advertising all IPs in all data centers, this group logic is applied, resiliency is improved because, if one of the data centers experiences a localized issue, the resolver can fall back to an IP advertised by the next closest data center. The third group adds another layer of redundancy, further enhancing resiliency.

Refer to [our blog post ↗](https://blog.cloudflare.com/foundation-dns-launch) for an in-depth explanation of the distributed groups logic.

Note

The IPs assigned to each nameserver are static, meaning they will not change without notification.

## Dedicated release process

Zones using advanced nameservers are less exposed to incidents or software regression.

The dedicated release process means that only changes that have been in production for a while will reach advanced nameservers.

## Nameservers hosting and assignment

While standard Cloudflare nameservers are hosted under `ns.cloudflare.com` or `secondary.cloudflare.com`, advanced nameservers use different domains:

* `foundationdns.com`
* `foundationdns.net`
* `foundationdns.org`

Using the different TLDs (`.com`, `.net`, and `.org`) and making these available only to enterprise accounts allows for better predictability and consistency in nameserver assignment.

There should also be less conflicts when guaranteeing that directly descending zones do not have the same nameserver set.

Descending zones example

Consider the domain `example.com`, and subdomains `abc.example.com` and `123.example.com`:

* `abc.example.com` and `123.example.com` directly descend from `example.com` and cannot have the same nameservers as `example.com`.
* `abc.example.com` and `123.example.com` are sibling domains and can have the same nameservers.
* `new.abc.example.com` directly descends from both `abc.example.com` and `example.com`, and cannot have the same nameservers as them, but can have the same nameservers as `123.example.com`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/foundation-dns/","name":"Foundation DNS"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/foundation-dns/advanced-nameservers/","name":"Advanced nameservers"}}]}
```

---

---
title: Custom nameservers
description: Use your own branded nameservers with Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Custom nameservers

With custom (or vanity) nameservers, a domain can use Cloudflare DNS without using Cloudflare-branded nameservers. For instance, you can configure `ns1.example.com` and `ns2.example.com` as nameservers for `example.com`.

To use custom nameservers, a zone must be using Cloudflare as Primary ([Full setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/)) or [Secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) DNS provider.

## Configuration scope

* [ Set up zone custom nameservers ](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/zone-custom-nameservers/)
* [ Set up account custom nameservers ](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/account-custom-nameservers/)
* [ Set up tenant custom nameservers ](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/tenant-custom-nameservers/)

## Availability

* Zone custom nameservers are available for zones on Business or Enterprise plans. Via API or on the dashboard.
* Account custom nameservers are available for customers on Business (after [contacting Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/)) or Enterprise plans. Once configured, account custom nameservers can be used by all zones in the account, regardless of the zone plan. Via API or on the dashboard.
* Tenant custom nameservers, if created by the tenant owner, will be available to all zones belonging to any account that is part of the tenant. Via API only.

## Restrictions

Custom nameservers are organized in different sets (`ns_set`). Each namesever set must have at least two and no more than five custom nameserver names.

The advantages that come with Foundation DNS [advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/advanced-nameservers/) are currently not available for [custom nameservers](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/). Make sure you only use one at a time.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/nameservers/","name":"Nameservers"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/nameservers/custom-nameservers/","name":"Custom nameservers"}}]}
```

---

---
title: Set up account custom nameservers
description: With account-level custom nameservers, you can use the same custom nameservers for different zones in the account. The domain or domains that provide the nameservers names do not have to exist as zones in Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Set up account custom nameservers

Account custom nameservers (ACNS) allow you to define account-level custom nameservers and use them for different zones within a Cloudflare account.

ACNS are organized in different sets (`ns_set`) and ACNS names can be provided by any domain, even if the domain does not exist as a zone in Cloudflare.

For instance, if the ACNS are `ns1.example.com` and `ns2.vanity.test`, the domains `example.com` and `vanity.test` are not required to be zones in Cloudflare.

## Availability

Account custom nameservers are available for customers on Business (after [contacting Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/)) or Enterprise plans. Once configured, account custom nameservers can be used by all zones in the account, regardless of the zone plan. Via API or on the dashboard.

Note

The advantages that come with Foundation DNS [advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/advanced-nameservers/) are currently not available for [custom nameservers](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/). Make sure you only use one at a time.

## Configuration conditions

For this configuration to be possible, a few conditions apply:

* You can create up to five different account custom nameserver sets. Each nameserver set must have between two and five different nameserver names (`ns_name`), and each name cannot belong to more than one set. For example, if `ns1.example.com` is part of `ns_set 1` it cannot be part of `ns_set 2` or vice versa.
* [Subdomain setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/) or [reverse zones](https://developers.cloudflare.com/dns/additional-options/reverse-zones/) can use account custom nameservers as long as they use a different nameserver set (`ns_set`) than their parent, child, or any other zone in their direct hierarchy tree.

Note

Account owners that want to [use their own IP prefix](https://developers.cloudflare.com/byoip/) for the account custom nameservers should contact their account team.

* Choosing a set from `ns_set 1` through `ns_set 5` will influence how Cloudflare assigns nameservers to your new zones if you configure [DNS zone defaults](https://developers.cloudflare.com/dns/nameservers/nameserver-options/#dns-zone-defaults).

## Enable account custom nameservers

### 1\. Set up ACNS names and sets

1. Create ACNS names and sets:

* [ Dashboard ](#tab-panel-7969)
* [ API ](#tab-panel-7970)

1. In the Cloudflare dashboard, go to the account **Settings** page.  
[ Go to **Configurations** ](https://dash.cloudflare.com/?to=/:account/configurations)
2. Go to **DNS Settings**.
3. For **Account custom nameservers**, select **Configure custom nameservers**.
4. Insert a fully qualified domain name for **Nameserver name** and choose a **Nameserver set**. Follow the [configuration conditions](#configuration-conditions).

Use the [Add account custom nameserver endpoint](https://developers.cloudflare.com/api/resources/custom%5Fnameservers/methods/create/) to create account custom nameservers. Follow the [conditions](#configuration-conditions) for `ns_name` and `ns_set`.

Note

If the parameter `ns_set` is omitted, the default set `1` will be assigned.

Cloudflare will assign an IPv4 and an IPv6 address to each ACNS name, and these nameservers will be listed as options that you can [use on existing zones](#2-use-acns-on-existing-zones) or [set up as default for new zones in the account](#3-optional-make-acns-default-for-new-zones).

1. Make sure `A/AAAA` records with the assigned IPv4 and IPv6 exist at the authoritative DNS of the domain that provides the ACNS names.  
   * If the domain uses Cloudflare DNS, the respective `A` and `AAAA` records are automatically created.  
   * If the domain or domains that are used for the account custom nameservers do not exist within the same account, you must manually create the `A/AAAA` records on the configured nameserver names (for example, `ns1.example.com`) at the authoritative DNS provider.

| Type | Name            | Content |
| ---- | --------------- | ------- |
| A    | ns1.example.com | <IPv4>  |

1. Update the registrar of the domain that provides the ACNS names. This step depends on whether you are using [Cloudflare Registrar](https://developers.cloudflare.com/registrar/):  
   * If you are using Cloudflare Registrar for the domain that provides the ACNS names, [contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) to add the account custom nameservers and IP addresses as glue records to the domain.  
   * If you are not using Cloudflare Registrar for the domain that provides the ACNS names, add the account custom nameservers and IP addresses to your domain's registrar as glue records ([RFC 1912 ↗](https://www.rfc-editor.org/rfc/rfc1912.html)). If you do not add these records, DNS lookups for your domain will fail.

### 2\. Use ACNS on existing zones

1. Choose an ACNS set as custom nameservers for a zone:

* [ Dashboard ](#tab-panel-7963)
* [ API ](#tab-panel-7964)

1. In the Cloudflare dashboard, go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. For **Custom nameservers**, select **Configure**.
3. Select **Use your account custom nameservers** and choose a nameserver set from the list.
4. Select **Save** to confirm.

Use the endpoint [Update DNS Settings for a Zone](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/methods/edit/) and configure the `nameservers` object accordingly for each zone.

1. Make sure the nameservers are updated:
* If your domain uses [Cloudflare Registrar](https://developers.cloudflare.com/registrar/), [contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) to update your nameservers.
* If your domain uses a different registrar, update the nameservers at your registrar to use the account custom nameservers.
* If your zone is delegated, update the corresponding `NS` record at the parent zone.

### 3\. (Optional) Make ACNS default for new zones

To make ACNS the default option for all new zones added to your account from now on:

* [ Dashboard ](#tab-panel-7967)
* [ API ](#tab-panel-7968)

1. In the Cloudflare dashboard, go to the account **Settings** page.  
[ Go to **Configurations** ](https://dash.cloudflare.com/?to=/:account/configurations)
2. Go to **DNS Settings**.
3. For **DNS zone defaults**, select **Configure defaults**.
4. Change the **Nameserver assignment method** to **Account custom nameservers**.

Refer to [DNS zone defaults](https://developers.cloudflare.com/dns/nameservers/nameserver-options/#dns-zone-defaults) for details.

Use the endpoint [Update DNS Settings for an Account](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/account/methods/edit/). Within the `zone_defaults` object, set the following:

```

"zone_defaults": {

  "nameservers": {

    "type": "custom.account"

  }

}


```

## Disable account custom nameservers

### 1\. Remove ACNS assignment from zones

To remove ACNS from a zone, first update your nameservers to stop using ACNS:

* [ Dashboard ](#tab-panel-7961)
* [ API ](#tab-panel-7962)

* If you are using [Cloudflare Registrar](https://developers.cloudflare.com/registrar/), [contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) to set your nameservers back to the regular Cloudflare branded nameservers.
* If you are not using [Cloudflare Registrar](https://developers.cloudflare.com/registrar/), modify the domain's registrar to use your regular Cloudflare branded nameservers.

* If you are using [Cloudflare Registrar](https://developers.cloudflare.com/registrar/), use the [Update DNS settings endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/methods/edit/) to set the `type` parameter in the `nameservers` object to `"cloudflare.standard"`. Then, [contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) to set your nameservers back to the regular Cloudflare branded nameservers.
* If you are not using [Cloudflare Registrar](https://developers.cloudflare.com/registrar/), modify the domain's registrar to use your regular Cloudflare branded nameservers and then use the [Update DNS settings endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/methods/edit/) to set the `type` parameter in the `nameservers` object to `"cloudflare.standard"`.

### 2\. Delete ACNS names or sets

Following the [configuration conditions](#configuration-conditions), each set must have between two and five different nameserver names. When you delete all names or leave a set with only one nameserver name, the set will no longer be listed as an option for the zones in your account.

* [ Dashboard ](#tab-panel-7965)
* [ API ](#tab-panel-7966)

1. In the Cloudflare dashboard, go to the account **Settings** page.  
[ Go to **Configurations** ](https://dash.cloudflare.com/?to=/:account/configurations)
2. Go to **DNS Settings**.
3. For **Account custom nameservers**, select **Delete** next to the ACNS name.

Use the [Delete account custom nameserver endpoint](https://developers.cloudflare.com/api/resources/custom%5Fnameservers/methods/delete/) to delete a specific ACNS.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/nameservers/","name":"Nameservers"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/nameservers/custom-nameservers/","name":"Custom nameservers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/nameservers/custom-nameservers/account-custom-nameservers/","name":"Set up account custom nameservers"}}]}
```

---

---
title: Set up tenant custom nameservers
description: With tenant-level custom nameservers, you can use the same custom nameservers for different zones and across different accounts, as long as the accounts are part of the [tenant](/tenant/). The domain or domains that provide the nameservers names do not have to exist as zones in Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Set up tenant custom nameservers

Tenant custom nameservers (TCNS) allow you to define tenant-level custom nameservers and use them for different accounts within a Cloudflare tenant.

TCNS are organized in different sets (`ns_set`) and TCNS names can be provided by any domain, even if the domain does not exist as a zone in Cloudflare.

For instance, if the TCNS are `ns1.example.com` and `ns2.vanity.test`, the domains `example.com` and `vanity.test` are not required to be zones in Cloudflare.

## Availability

Tenant custom nameservers, if created by the tenant owner, will be available to all zones belonging to any account that is part of the tenant. Via API only.

## Configuration conditions

For this configuration to be possible, a few conditions apply:

* Tenant owners can create up to five different tenant custom nameserver sets. Each nameserver set must have between two and five different nameserver names (`ns_name`), and each name cannot belong to more than one set. For example, if `ns1.example.com` is part of `ns_set 1` it cannot be part of `ns_set 2` or vice versa.
* [Subdomain setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/) or [reverse zones](https://developers.cloudflare.com/dns/additional-options/reverse-zones/) can use tenant custom nameservers as long as they use a different nameserver set (`ns_set`) than their parent, child, or any other zone in their direct hierarchy tree.

Note

Tenant owners that want to [use their own IP prefix](https://developers.cloudflare.com/byoip/) for the tenant custom nameservers should contact their account team.

## For account owners

### Enable tenant custom nameservers on a zone

If you are an account owner and your account is part of a tenant that has custom nameservers, do the following:

1. Use the endpoint [Update DNS Settings for a Zone](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/methods/edit/) and configure the `nameservers` object accordingly.  
```  
  "nameservers": {  
    "type": "custom.tenant"  
  }  
```  
Note  
If the parameter `ns_set` is omitted, the default set `1` will be assigned.
2. If you are **not** using [Cloudflare Registrar](https://developers.cloudflare.com/registrar/), update the nameservers at your registrar to use the TCNS names. If you are using [Cloudflare Registrar](https://developers.cloudflare.com/registrar/), no further action is needed.

To make these TCNS the default namerservers for all new zones added to your account from now on, use the endpoint [Update DNS Settings for an Account](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/account/methods/edit/). Within the `zone_defaults` object, set the following:

```

"zone_defaults": {

  "nameservers": {

    "type": "custom.tenant"

  }

}


```

### Disable tenant custom nameservers on a zone

* If you are using [Cloudflare Registrar](https://developers.cloudflare.com/registrar/), use the [Update DNS settings endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/methods/edit/) to set the `type` parameter in the `nameservers` object to a different value. Then, [contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) to set your nameservers back to the nameservers you chose to use.
* If you are not using Cloudflare Registrar, use the [Update DNS settings endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/methods/edit/) to choose a different nameserver type, and also remove the TCNS at your domain's registrar.

## For tenant owners

### Create tenant custom nameservers

If you are a tenant owner and you want to make TCNS available for accounts within your tenant, do the following:

1. Observe the [conditions](#configuration-conditions) for `ns_name` and `ns_set`, and create TCNS in your tenant by using the following POST command:

Terminal window

```

curl https://api.cloudflare.com/client/v4/tenants/{tenant_id}/custom_ns \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data '{

  "ns_name": "<NS_NAME>",

  "ns_set": <SET>

}'


```

Note

If the parameter `ns_set` is omitted, the default set `1` will be assigned.

1. Add the account custom nameservers and IP addresses to your domain's registrar as glue (A and AAAA) records ([RFC 1912 ↗](https://www.rfc-editor.org/rfc/rfc1912.html)).
2. If the domain or domains that are used for the tenant custom nameservers do not exist within the same account, you must create the `A/AAAA` records on the configured nameserver names (for example, `ns1.example.com`) at the authoritative DNS provider.

| Type | Name            | Content |
| ---- | --------------- | ------- |
| A    | ns1.example.com | <IPv4>  |

### Get a list of all TCNS names

To get a list of all TCNS names in your tenant account, use the following API request:

Terminal window

```

curl https://api.cloudflare.com/client/v4/tenants/{tenant_id}/custom_ns \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>"


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/nameservers/","name":"Nameservers"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/nameservers/custom-nameservers/","name":"Custom nameservers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/nameservers/custom-nameservers/tenant-custom-nameservers/","name":"Set up tenant custom nameservers"}}]}
```

---

---
title: Set up zone custom nameservers
description: With zone-level custom nameservers, each custom nameserver name must be a subdomain of the zone where the custom nameservers are configured. These custom nameservers can only be used within the respective zone.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Set up zone custom nameservers

With zone custom nameservers (ZCNS), each custom nameserver name must be a subdomain of the zone where the custom nameservers are configured.

For example, for a zone `domain.test`, the ZCNS can be `ns1.domain.test` and `ns2.domain.test` but they cannot use a different TLD (`ns1.domain.org`) nor a different domain (`ns1.example.com`).

## Availability

Zone custom nameservers are available for zones on Business or Enterprise plans. Via API or on the dashboard.

## Use zone custom nameservers

### Primary zones (full setup)

To create zone custom nameservers:

* [ Dashboard ](#tab-panel-7971)
* [ API ](#tab-panel-7972)

1. In the Cloudflare dashboard, go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. On **Custom nameservers**, select **Configure**.
3. Select **Create custom nameservers just for `your-domain.com`** and enter the subdomains used for the ZCNS names (for example, `ns1`, `ns2`, `ns3`).
4. Select **Save** to confirm.

Use the [Edit zone endpoint](https://developers.cloudflare.com/api/resources/zones/methods/edit/) and specify the custom nameservers in the payload:

```

"vanity_name_servers": ["ns1.example.com","ns2.example.com"]


```

Cloudflare will assign an IPv4 and an IPv6 address to each ZCNS name and automatically create the associated `A` or `AAAA` records.

The next step depends on whether you are using [Cloudflare Registrar](https://developers.cloudflare.com/registrar/) for your domain:

* If you are using Cloudflare Registrar for your domain, [contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) to add the custom nameservers and IP addresses as glue records to the domain.
* If you are not using Cloudflare Registrar for your domain, add the zone custom nameservers at your registrar as your authoritative nameservers and as glue (A and AAAA) records ([RFC 1912 ↗](https://www.rfc-editor.org/rfc/rfc1912.html)). If you do not add these records, DNS lookups for your domain will fail.

### Secondary zones

If you are using [Cloudflare as a secondary DNS provider](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/), you can still set up zone custom nameservers. After following the [steps above](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/zone-custom-nameservers/#primary-zones-full-setup) to create zone custom nameservers, do the following:

1. Get the ZCNS IPs. You can find them on the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page or you can use the [Zone details endpoint](https://developers.cloudflare.com/api/resources/zones/methods/get/) to get the `vanity_name_servers_ips`.
2. At your primary DNS provider, add [NS records](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#ns) and, on the subdomains that you used as ZCNS names, add `A/AAAA` records.
3. At your registrar, add the zone custom nameservers as your authoritative nameservers and as glue (A and AAAA) records ([RFC 1912 ↗](https://www.rfc-editor.org/rfc/rfc1912.html)).

## Remove zone custom nameservers

To remove zone custom nameservers (and their associated, read-only DNS records):

* [ Dashboard ](#tab-panel-7973)
* [ API ](#tab-panel-7974)

1. In the Cloudflare dashboard, go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. On **Custom nameservers**, select **Disable**.

Use the [Edit zone endpoint](https://developers.cloudflare.com/api/resources/zones/methods/edit/) and include an empty array in the payload:

```

"vanity_name_servers": []


```

Cloudflare will remove your ZCNS and their associated read-only `A` or `AAAA` records.

If you are not using Cloudflare Registrar for your domain, make sure to adjust your nameservers at the registrar, parent zone, or Primary DNS provider accordingly.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/nameservers/","name":"Nameservers"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/nameservers/custom-nameservers/","name":"Custom nameservers"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/nameservers/custom-nameservers/zone-custom-nameservers/","name":"Set up zone custom nameservers"}}]}
```

---

---
title: Nameserver options
description: Available nameserver configuration options.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Nameserver options

Refer to the sections below to learn about different Cloudflare nameserver options. Note that the availability of these options depends on your plan. Also, if you acquired your domain from Cloudflare Registrar, your domain already uses and [must remain](https://developers.cloudflare.com/registrar/faq/#can-i-change-my-nameservers) on Cloudflare nameservers.

## Assignment method

When you add a domain on a [primary (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/) or [secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) DNS setup, Cloudflare automatically assigns your nameservers.

The default assignment method is to use [standard nameservers](https://developers.cloudflare.com/dns/nameservers/#standard-nameservers) and favor consistent nameserver names across all zones within an account. Nonetheless, in case there are conflicts, you may get different nameserver names, even for domains that are within the same account.

Warning

To prevent domain hijacking, you can no longer preset Cloudflare nameservers at your registrar before creating the respective zone in Cloudflare. If you preset your nameservers and then add the domain, your domain will be assigned a new pair of nameservers.

These nameserver assignments cannot be changed. However, depending on your subscription, you may have different options for better nameserver consistency.

### Nameserver consistency

The level of consistency you can expect when adding new zones depends on the configured nameserver type.

* For [standard nameservers](https://developers.cloudflare.com/dns/nameservers/#standard-nameservers), since a conflict can be caused by anyone adding the same zone to any other Cloudflare account, the likelihood of your new zone being assigned different nameserver names than your previously existing zones is higher.
* If you use [account custom nameservers](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/account-custom-nameservers/), the only conflict would be between a parent and a child zone, which makes consistent assignment across new zones more likely.
* With [tenant custom nameservers](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/tenant-custom-nameservers/) or [Foundation DNS advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/advanced-nameservers/#nameservers-hosting-and-assignment), there can still be conflicts caused by two zones with the same name being added to different accounts, but, since access to these features is more restricted, the likelihood of your new zone being assigned different nameserver names than your previously existing zones is lower.

### DNS zone defaults

If you have an Enterprise account, you also have the option to [configure your own DNS zone defaults](https://developers.cloudflare.com/dns/additional-options/dns-zone-defaults/) and change how Cloudflare handles nameserver assignment when you add a new zone to your account:

* **Standard nameservers randomized**: instead of attempting consistency, Cloudflare assigns random pairs of nameserver names every time you add a new domain to your account.
* **Advanced nameservers**: Cloudflare uses the same method as the default - trying to keep nameserver names consistent for different zones within an account - but uses the specific [Foundation DNS nameservers](https://developers.cloudflare.com/dns/foundation-dns/advanced-nameservers/).
* **Account custom nameservers**: Cloudflare automatically assigns a set of [account custom nameservers](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/account-custom-nameservers/) that you have previously configured for your account. In this method, **Set 1** will be attempted first and, in case of any conflicts, Cloudflare will cycle through the other nameserver sets, in ascending order.

Warning

DNS zone defaults are only applied at the moment a new zone is created and will not impact already existing zones, nor zones that existed previously and are being revived.

Any of the values specified as default can later be adjusted within each zone, on the respective [**DNS Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings) or [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page.

## Multi-provider DNS

Multi-provider DNS is an optional setting for zones using [primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/) and is an enforced default behavior for zones using [secondary setup](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/).

When you enable multi-provider DNS on a primary zone:

* Cloudflare will no longer ignore `NS` records created on the zone apex, as in the example below.  
| Type | Name | Nameserver       |  
| ---- | ---- | ---------------- |  
| NS   | @    | ns1.external.com |

This means that responses to DNS queries made to the zone apex and requesting `NS` records will contain both Cloudflare's and your other DNS providers' nameservers.

* Cloudflare will activate a primary zone (full setup) even if its [nameservers listed at the registrar](https://developers.cloudflare.com/dns/nameservers/update-nameservers/) include nameservers from other DNS providers.

Warning

If you choose this option and you also want to use DNSSEC on your zone, make sure to set up [multi-signer DNSSEC](https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/).

## Nameserver TTL

For both Cloudflare nameservers (standard or advanced) and custom nameservers, the `NS` record time-to-live (TTL) is controlled by the specific setting on the **DNS Records** page, under **DNS record options**.

Foundation DNS

**DNS record options** are part of [Foundation DNS](https://developers.cloudflare.com/dns/foundation-dns/). If you are an Enterprise customer and **Nameserver TTL** is not displayed on your Cloudflare dashboard, reach out to your account team.

The default TTL is 24 hours (or 86,400 seconds), but you have the option to lower this value depending on your needs. For example, shorter TTLs can be useful when you are changing nameservers or migrating a zone. Accepted values range from 30 to 86,400 seconds.

This setting can also be configured as a [DNS zone default](https://developers.cloudflare.com/dns/additional-options/dns-zone-defaults/), meaning new zones created in your account will automatically start with the value you define.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/nameservers/","name":"Nameservers"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/nameservers/nameserver-options/","name":"Nameserver options"}}]}
```

---

---
title: Update nameservers
description: Update your domain registrar to use Cloudflare nameservers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Update nameservers

To use Cloudflare DNS as an authoritative DNS provider - be it in a [primary (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/) or [secondary](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) setup -, your domain nameservers must point to nameservers that you get from your Cloudflare account. Updating your nameservers is required to activate your domain on Cloudflare and use most of our [application services](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/).

Cloudflare Registrar

If you acquired your domain from [Cloudflare Registrar](https://developers.cloudflare.com/registrar/), your domain already uses Cloudflare nameservers, automatically protecting and speeding up your content or services. If you need to update your nameservers to use a different DNS provider, you will have to [transfer your domain from Cloudflare](https://developers.cloudflare.com/registrar/account-options/transfer-out-from-cloudflare/).

---

## Specific processes

Although Cloudflare will [provide you the nameservers](https://developers.cloudflare.com/dns/nameservers/#authoritative-nameservers-offering) or allow you to create your own [custom nameservers](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/), the final step to make Cloudflare an authoritative DNS provider for your domain may have to be done outside of Cloudflare. If you are not using [Cloudflare Registrar](https://developers.cloudflare.com/registrar/), consider which of the following sections correspond to your use case.

Custom or advanced nameservers

If you are using Cloudflare Registrar with [custom nameservers](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/) or [advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/setup/), note that you must [reach out to support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) to have the nameservers updated accordingly.

### Your domain uses a different registrar

If you have acquired your domain from a [registrar ↗](https://www.cloudflare.com/learning/dns/glossary/what-is-a-domain-name-registrar/) other than Cloudflare Registrar - and it has not been [delegated](#your-domain-is-delegated) \- you need to update your nameservers at your registrar.

If you do not know who your registrar is, you can use a Whois search, such as [ICANN Lookup ↗](https://lookup.icann.org/). If the registrar indicated on your Whois search result is not a service that you have interacted directly with, you may [have acquired your domain from a reseller](#you-have-acquired-your-domain-from-a-reseller).

Provider-specific instructions

This is not an exhaustive list of provider-specific instructions, but the following links may be helpful:

* [Ionos ↗](https://www.ionos.com/help/domains/using-your-own-name-servers/using-your-own-name-servers-for-a-domain/)
* [101Domain ↗](https://help.101domain.com/kb/managing-name-server-records)
* [Amazon ↗](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-name-servers-glue-records.html#domain-name-servers-glue-records-adding-changing)
* [Blacknight ↗](https://help.blacknight.com/hc/articles/4413036322321-How-do-I-change-the-nameservers-for-my-domain)
* [BlueHost ↗](https://www.bluehost.com/help/article/custom-nameservers)
* [DirectNIC ↗](https://directnic.com/knowledge/article/33:how%2Bdo%2Bi%2Bmodify%2Bname%2Bservers%2Bfor%2Bmy%2Bdomain%2Bname%253F)
* [DNSMadeEasy ↗](http://www.dnsmadeeasy.com/support/faq/)
* [Domain.com ↗](https://www.domain.com/help/article/domain-management-how-to-update-nameservers)
* [Dotster ↗](https://www.dotster.com/help/article/domain-management-how-to-update-nameservers)
* [DreamHost ↗](https://help.dreamhost.com/hc/en-us/articles/360038897151)
* [EasyDNS ↗](https://kb.easydns.com/knowledge/settingchanging-nameservers/)
* [Enom ↗](https://help.enom.com/hc/en-us/articles/115000486451-Nameservers-NS)
* [Fast Domain ↗](https://www.fastdomain.com/hosting/help/transfer%5Fclient%5Fstart)
* [FlokiNET ↗](https://billing.flokinet.is/index.php?rp=/knowledgebase/57/Nameserver-and-DNS-records.html)
* [Gandi ↗](https://docs.gandi.net/en/domain%5Fnames/common%5Foperations/changing%5Fnameservers.html)
* [GoDaddy ↗](https://www.godaddy.com/help/change-nameservers-for-your-domain-names-664)
* [HostGator ↗](https://www.hostgator.com/help/article/changing-name-servers)
* [Hostico ↗](https://hostico.ro/docs/setarea-nameserverelor-din-contul-de-client-hostico/)
* [HostMonster ↗](https://my.hostmonster.com/cgi/help/222)
* [Hover ↗](https://support.hover.com/support/solutions/articles/201000064742-changing-your-domain-nameservers)
* [Internetdbs ↗](https://faq.internetbs.net/hc/en-gb/articles/4516921367837-How-to-update-Nameservers-for-a-domain)
* [iPage ↗](https://www.ipage.com/help/article/domain-management-how-to-update-nameservers)
* [MelbourneIT ↗](https://support.melbourneit.au/docs/how-do-i-manage-my-dns-on-cpanel)
* [Moniker ↗](https://support.moniker.com/hc/en-gb/articles/10101271418653-How-to-update-Nameservers-for-a-domain)
* [Name.com ↗](https://www.name.com/support/articles/205934457-registering-custom-nameservers)
* [Namecheap ↗](https://www.namecheap.com/support/knowledgebase/article.aspx/767/10/how-can-i-change-the-nameservers-for-my-domain)
* [Network Solutions ↗](https://www.networksolutions.com/manage-it/edit-nameservers.jsp)
* [OVH ↗](https://docs.ovh.com/gb/en/domains/web%5Fhosting%5Fgeneral%5Finformation%5Fabout%5Fdns%5Fservers/#step-2-edit-your-domains-dns-servers)
* [Porkbun ↗](https://kb.porkbun.com/article/22-how-to-change-your-nameservers)
* [Rackspace ↗](https://support.rackspace.com/how-to/rackspace-name-servers/)
* [Register ↗](https://www.register.com/knowledge)
* [Squarespace ↗](https://support.squarespace.com/hc/articles/4404183898125-Nameservers-and-DNSSEC-for-Squarespace-managed-domains#toc-open-the-domain-s-advanced-settings)
* [Site5 ↗](https://kb.site5.com/dns-2/custom-nameservers/)
* [Softlayer ↗](https://cloud.ibm.com/docs/dns?topic=dns-add-edit-or-delete-custom-name-servers-for-a-domain)
* [Yola ↗](https://helpcenter.yola.com/hc/articles/360012492660-Changing-your-name-servers)

### You have acquired your domain from a reseller

Some services, such as website builders ([Squarespace ↗](https://support.squarespace.com/hc/articles/115003671428-Who-s-my-domain-provider), for example), are not registrars but act as a [reseller ↗](https://www.icann.org/resources/pages/reseller-2013-05-03-en), allowing you to buy domains directly from them.

In that case, you may have to update your nameservers in the reseller platform, not at the registrar.

Note

Refer to [Squarespace documentation ↗](https://support.squarespace.com/hc/articles/4404183898125-Nameservers-and-DNSSEC-for-Squarespace-managed-domains#toc-open-the-domain-s-advanced-settings) on how to update nameservers in their platform.

### Your domain is delegated

If you are onboarding a subdomain `shop.example.com` as a [child domain](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/), the parent domain (`example.com`) must delegate authority to the child domain.

Delegation means that `shop.example.com` has specific `NS` records set up for it within the DNS records management of the parent zone (`example.com`).

If that is the case, when setting up your zone in Cloudflare or opting for a different set of [nameservers](https://developers.cloudflare.com/dns/nameservers/), you have to update the `NS` records in the parent domain, and not at the registrar.

---

## Restricted nameserver management

Some providers act as registrars but do not expose nameserver settings. If you cannot change nameservers at your registrar or hosting platform, you can either:

* Transfer your domain to a registrar that allows nameserver management.
* Transfer your domain to Cloudflare Registrar. All domains on [Cloudflare Registrar](https://developers.cloudflare.com/registrar/) automatically use Cloudflare nameservers.
* Use a [CNAME setup (partial)](https://developers.cloudflare.com/dns/zone-setups/partial-setup/) instead. This option does not require nameserver changes and is available on Business and Enterprise plans.

---

## Further guidance

This page covers specific workflows that customers who do not use Cloudflare Registrar[1](#user-content-fn-1) might have to follow to update their domain nameservers. For complete tutorials, refer to the pages below. Full setup is the most common option, and the only one available for customers on the Free or Pro plans.

* [ Primary setup (Full) ](https://developers.cloudflare.com/dns/zone-setups/full-setup/)
* [ CNAME setup (Partial) ](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)
* [ DNS Zone transfers ](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/)
* [ Subdomain setup ](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/)
* [ Reference ](https://developers.cloudflare.com/dns/zone-setups/reference/)
* [ Troubleshooting ](https://developers.cloudflare.com/dns/zone-setups/troubleshooting/)
* [ DNS setup conversions ](https://developers.cloudflare.com/dns/zone-setups/conversions/)
* [ Zone removal ](https://developers.cloudflare.com/dns/zone-setups/removal/)

## Footnotes

1. If you acquired your domain from Cloudflare Registrar, your domain already uses and must remain on Cloudflare nameservers. For details, refer to [Registrar](https://developers.cloudflare.com/registrar/faq/#can-i-change-my-nameservers). [↩](#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":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/nameservers/","name":"Nameservers"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/nameservers/update-nameservers/","name":"Update nameservers"}}]}
```

---

---
title: DNS records
description: Manage DNS records for your Cloudflare zones.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNS records

DNS records contain information about your domain and are used to make your website or application available to visitors and other web services.

Each DNS record belongs to a different type, and each type serves a different purpose. For background about the different types of DNS records, refer to the [Learning Center ↗](https://www.cloudflare.com/learning/dns/dns-records/). To quickly find reference information about a specific type, refer to [DNS record types](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/).

Depending on the providers you used to [get your domain name](https://developers.cloudflare.com/fundamentals/manage-domains/#get-a-domain-name) and [host your website or application](https://developers.cloudflare.com/fundamentals/manage-domains/#host-your-domain), it is expected that DNS records were automatically created on your behalf. According to your [setup](https://developers.cloudflare.com/dns/zone-setups/), you can use Cloudflare to manage your DNS records.

## DNS records table

When managing your records at Cloudflare, besides the common record fields described below, you may also find an option for [Proxy status](https://developers.cloudflare.com/dns/proxy-status/) and [CNAME flattening](https://developers.cloudflare.com/dns/cname-flattening/). These are specific features offered by Cloudflare.

Record fields

* **Type**: Defines the purpose of a record. Different types of record require different information in their corresponding `Content` field.
* **Name**: Identifies the resource that the record resolves to. Depending on the purpose of the record, the value you want to add to this field will also change.
* **Content**: Contains the core value of a record, depending on the record type.
* **TTL**: Controls how long each record is cached by DNS resolvers.

Example

DNS management for **example.com**:

| Type | Name | Content   | Proxy status | TTL  |
| ---- | ---- | --------- | ------------ | ---- |
| A    | blog | 192.0.2.1 | Proxied      | Auto |

In this example, an IP address resolution record of type `A` is indicating that the resources that correspond to the subdomain `blog.example.com` can be reached on the IPv4 address `192.0.2.1`.

Also, as this record is [proxied](https://developers.cloudflare.com/dns/proxy-status/), Cloudflare automatically defines for how long this information should be cached by DNS resolvers.

## DNS records quota

Cloudflare limits the number of DNS records you can create. Depending on your plan, this limit is enforced either per zone or per account — not both.

DNS records that other Cloudflare services create on your behalf also count toward your quota.

### Per-zone quota

By default, there is a limit to the number of records you can create on a single zone.

* Free zones created before `2024-09-01 00:00:00 UTC`: 1,000
* Free zones created on or after `2024-09-01 00:00:00 UTC`: 200
* Pro: 3,500
* Business: 3,500
* Enterprise: 3,500

You can retrieve a zone's current quota (if applicable) and usage [via the API](https://developers.cloudflare.com/api/resources/dns/subresources/usage/subresources/zone/methods/get/).

### Per-account quota

Enterprise accounts have a quota on the total number of records across all of their zones, instead of the per-zone limit. This lets you distribute records across your zones however you like, regardless of each zone's plan.

Public zones and [internal zones](https://developers.cloudflare.com/dns/internal-dns/) are counted separately, each with a default account quota of 1,000,000 records.

You can retrieve your current account quota and usage [via the API](https://developers.cloudflare.com/api/resources/dns/subresources/usage/subresources/account/methods/get/).

For more DNS records

If you are an Enterprise customer and require a higher account quota, contact your account team. Cloudflare can support millions of DNS records.

## Resources

### How to

* [ Manage DNS records ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/)
* [ Create zone apex record ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-zone-apex/)
* [ Create subdomain records ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-subdomain/)
* [ Set up email records ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/email-records/)
* [ Import and export records ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/)
* [ Batch record changes ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/batch-record-changes/)
* [ Dynamically update DNS records ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/managing-dynamic-ip-addresses/)
* [ Round-robin DNS ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/round-robin-dns/)
* [ Delegate subdomains ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/subdomains-outside-cloudflare/)

### Reference

* [ DNS record types ](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/)
* [ Time to Live (TTL) ](https://developers.cloudflare.com/dns/manage-dns-records/reference/ttl/)
* [ Record attributes ](https://developers.cloudflare.com/dns/manage-dns-records/reference/record-attributes/)
* [ Vendor-specific DNS records ](https://developers.cloudflare.com/dns/manage-dns-records/reference/vendor-specific-records/)
* [ Wildcard DNS records ](https://developers.cloudflare.com/dns/manage-dns-records/reference/wildcard-dns-records/)

### Troubleshooting

* [ Records with the same name ](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/records-with-same-name/)
* [ Unexpected DNS records ](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/unexpected-dns-records/)
* [ Exposed IP addresses ](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/exposed-ip-address/)
* [ Verify a domain with CNAME ](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/cname-domain-verification/)
* [ NS records already exist ](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/existing-ns-record/)
* [ Stale response for upstream DNS resolution ](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/stale-response/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}}]}
```

---

---
title: Batch record changes
description: Create, update, and delete multiple DNS records at once.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Batch record changes

Cloudflare allows you to apply several changes to your zone records in just one action. You can [use the dashboard](#use-the-dashboard) to delete DNS records or update their proxy status in bulk, or [use the API](#use-the-api) to perform further batched operations.

Propagation through the Cloudflare network

Although Cloudflare will execute the batched operations in a single [database transaction ↗](https://en.wikipedia.org/wiki/Database%5Ftransaction), Cloudflare's distributed KV store must treat each record change as a single key-value pair. This means that the propagation of changes is not atomic. Refer to our [blog post ↗](https://blog.cloudflare.com/batched-dns-changes/) for details.

## Availability and limits

Batch DNS record changes is available on all plans.

The number of records that you can operate with in one action depends on your zone plan:

* Free: 200
* Pro: 3,500
* Business: 3,500
* Enterprise: 3,500

---

## Use the dashboard

### Edit proxy status in bulk

`A`,`AAAA`, and `CNAME` records can be [proxied](https://developers.cloudflare.com/dns/proxy-status/). The **Proxy status** of a DNS record affects [how Cloudflare responds to DNS queries](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/) to that record.

Note

If you have multiple `A/AAAA` records on the same name and at least one of them is proxied, Cloudflare will treat all `A/AAAA` records on this name as being proxied.

1. In the Cloudflare dashboard, go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. Select the DNS records you want to set the proxy status for. Note that only `A`, `AAAA`, and `CNAME` records can be proxied.
3. Select **Edit records**.
4. Choose the proxy status you want to apply to the selected records.
5. Select **Save** to confirm.

You can only set records to either **Proxied** or **DNS only** in bulk. This means that if your selection includes both proxied and DNS-only records, some of them will have the proxy status updated while others will keep their original value:

For example, if you select the following records and then edit their proxy status in bulk, choosing **Proxied** in [step 4 above](#edit-proxy-status-in-bulk), the outcome will be:

| Selected records | Original proxy status | Resulting proxy status |
| ---------------- | --------------------- | ---------------------- |
| www              | DNS only              | Proxied                |
| blog             | DNS only              | Proxied                |
| docs             | Proxied               | Proxied                |

### Delete records in bulk

Warning

Deleting DNS records can cause downtime and cannot be reverted. Make sure you only select DNS records that you can safely delete.

1. In the Cloudflare dashboard, go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. Select the DNS records you want to delete.
3. Select **Delete records**.
4. In the **Delete DNS records** prompt, type in `DELETE` and select **Delete** to confirm.

## Use the API

Note

This option requires familiarity with API usage and concepts. For further information about the Cloudflare API, refer to [Fundamentals](https://developers.cloudflare.com/fundamentals/api/get-started/).

The [Batched DNS record changes](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/batch/) endpoint allows you to trigger the execution of `DELETES`, `PATCHES`, `PUTS`, and `POSTS` in a single request.

[Tags and comments](https://developers.cloudflare.com/dns/manage-dns-records/reference/record-attributes/) are also supported with batch changes.

The operations you specify within the `/batch` request body are always executed in the following order:

1. Deletes
2. Patches
3. Puts
4. Posts

Within each of these four lists, each individual action is executed following the DNS records order you provide. If any of the individual action fails, no changes are applied and the API returns the first error it encountered.

### Aspects to consider

Propagation through the Cloudflare network

Although Cloudflare will execute the batched operations in a single [database transaction ↗](https://en.wikipedia.org/wiki/Database%5Ftransaction), Cloudflare's distributed KV store must treat each record change as a single key-value pair. This means that the propagation of changes is not atomic. Refer to our [blog post ↗](https://blog.cloudflare.com/batched-dns-changes/) for details.

For each operation that you list in the `/batch` request body, consider the required information and how unspecified fields will behave:

* **`deletes`**: only the `id` is required for each record object. You can keep additional parameters such as `name` for readability, but any other fields aside from `id` will be ignored in this case.
* **`patches`**: aside from each record `id`, you should specify the fields you want to update. All unspecified fields will remain as they are.
* **`puts`**: you must specify each record `id`, `content`, `name`, and `type`. You should also specify any other fields you want to set to a value that is not the default. Any unspecified fields will assume their default value for each [record type](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/). This operation works as an overwrite, so all fields in a given record are always affected.
* **`posts`**: since you are creating a new record, `id` is not required. For field definitions, refer to the [Create DNS Record](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) endpoint and select the desired record type under the request body specification.

### Example request

In this example, the `proxied` field for the first record listed under `"puts"` will assume the default value (`false`).

Terminal window

```

{

    "deletes": [

        {

            "id": "2bff0ebc4df64beaa44b0dca93e37a28"

        },

        {

            "id": "31d1d6e79ce04b8d93cbc5a13401d728"

        }

    ],

    "patches": [

        {

            "id": "62276440f783445380480484648c1017",

            "content": "192.0.2.46"

        },

        {

            "id": "c942d948dc2343b9b97aed78479c9fb9",

            "name": "update.example.com",

            "proxied": true

        }

    ],

    "puts": [

        {

            "id": "a50364543094428abde0f14061d42b0e",

            "content": "192.0.2.50",

            "name": "change.example.com",

            "type": "A",

            "ttl:": 1

        },

        {

            "id": "3bce0920f19d43949498bd067b05dfa9",

            "content": "192.0.2.45",

            "name": "no-change.example.com",

            "type": "A",

            "proxied": false,

            "ttl:": 3000

        }

    ],

    "posts": [

        {

            "name": "@",

            "type": "A",

            "content": "192.0.2.41",

            "proxied": false,

            "ttl": 3000

        },

        {

            "name": "a.example.com",

            "type": "A",

            "content": "192.0.2.42",

            "proxied": true

        }

    ]

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/how-to/","name":"How to"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/how-to/batch-record-changes/","name":"Batch record changes"}}]}
```

---

---
title: Manage DNS records
description: Create, edit, and delete DNS records for your zone.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Manage DNS records

Consider the sections below for step-by-step instructions on managing DNS records at Cloudflare.

To better understand what DNS records are, refer to [Overview](https://developers.cloudflare.com/dns/manage-dns-records/). For context around common records you want to review when getting started at Cloudflare, refer to [review DNS records](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/#2-review-your-dns-records).

Note

If your domain is added to Cloudflare by a hosting partner, manage your DNS records via the hosting partner.

---

## Basic operations

### Create DNS records

* [ Dashboard ](#tab-panel-7951)
* [ API ](#tab-panel-7952)

To create a DNS record in the dashboard:

1. In the Cloudflare dashboard, go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. Select **Add record**.
3. Choose a record [**Type**](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/).
4. Complete the required fields, which vary per record. Particularly important fields (for some records) include:  
   * **Proxy status**: For `A`, `AAAA`, and `CNAME` records, decide whether hostname traffic is [proxied through Cloudflare](https://developers.cloudflare.com/dns/proxy-status/).  
   * **TTL**: Short for [_Time to Live_](https://developers.cloudflare.com/dns/manage-dns-records/reference/ttl/), this field controls how long each record is valid and — as a result — how long it takes for record updates to reach your end users.  
   * **Comment** and **Tag**: [Record attributes](https://developers.cloudflare.com/dns/manage-dns-records/reference/record-attributes/) meant for your reference.  
   * **Private network routing**: Some Enterprise customers also have access to [private network routing](https://developers.cloudflare.com/dns/private-origins/private-network-routing/). For `A` and `AAAA` records, this feature allows you to proxy HTTP/HTTPS traffic from public hostnames to origins in your private network.
5. Select **Save**.

To create records with the API, use a [POST request](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/). For field definitions, select a record type under the request body specification.

For specific API examples, refer to [DNS record types](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/).

### Edit DNS records

* [ Dashboard ](#tab-panel-7947)
* [ API ](#tab-panel-7948)

To edit DNS records in the dashboard:

1. In the Cloudflare dashboard, go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. On a specific record, select **Edit**.
3. Make any necessary changes.
4. Select **Save**.

To update part of a record with the API, use a [PATCH request](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/edit/). If you want to overwrite the entire existing record, use a [PUT request](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/update/).

### Delete DNS records

* [ Dashboard ](#tab-panel-7949)
* [ API ](#tab-panel-7950)

To delete DNS records in the dashboard:

1. In the Cloudflare dashboard, go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. On a specific record, select **Edit**.
3. Select **Delete**.
4. Select **Delete** again to confirm.

To delete records with the API, use a [DELETE request](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/delete/).

---

## Use cases

### Update an origin IP address

If your hosting provider changes or your origin IP address changes, update the **Content** value of the relevant DNS records (usually `A` or `AAAA` records).

If you are not sure which IP address to use, refer to your hosting provider's documentation.

### Originless setups

If you need a placeholder address for an originless setup (also referred to as parked domain or redirect-only), you can use the reserved IPv6 address `100::` or the reserved IPv4 address `192.0.2.0` in a [proxied](https://developers.cloudflare.com/dns/proxy-status/) DNS record.

This allows you to route requests using products such as [Redirect Rules](https://developers.cloudflare.com/rules/url-forwarding/), [Page Rules](https://developers.cloudflare.com/rules/page-rules/), or [Workers](https://developers.cloudflare.com/workers/).

Note

The address `192.0.2.0` comes from an IPv4 range reserved for documentation ([RFC 5737 ↗](https://www.rfc-editor.org/rfc/rfc5737)), and `100::` comes from the IPv6 discard prefix `0100::/64` ([RFC 6666 ↗](https://www.rfc-editor.org/rfc/rfc6666)). Neither address is expected to route to a real server on properly configured networks, which makes them safe to use as placeholder values. Because the DNS record is proxied, Cloudflare intercepts the request before it reaches the origin address.

---

## Further guidance

* [ Manage DNS records ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/)
* [ Create zone apex record ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-zone-apex/)
* [ Create subdomain records ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-subdomain/)
* [ Set up email records ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/email-records/)
* [ Import and export records ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/)
* [ Batch record changes ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/batch-record-changes/)
* [ Dynamically update DNS records ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/managing-dynamic-ip-addresses/)
* [ Round-robin DNS ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/round-robin-dns/)
* [ Delegate subdomains ](https://developers.cloudflare.com/dns/manage-dns-records/how-to/subdomains-outside-cloudflare/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/how-to/","name":"How to"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/how-to/create-dns-records/","name":"Manage DNS records"}}]}
```

---

---
title: Create subdomain records
description: Add DNS records for subdomains.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Create subdomain records

Most subdomains serve a specific purpose within the overall context of your website. For example, `blog.example.com` might be your blog, `support.example.com` could be your customer help portal, and `store.example.com` would be your e-commerce site.

Even if you do not require specific subdomains, you might want to set up at least a subdomain record on `www`. It will usually point to the same content as what you have on the apex domain (`example.com`) or use a [redirect](https://developers.cloudflare.com/fundamentals/manage-domains/manage-subdomains/#redirect-a-subdomain-to-the-apex-domain). Having a subdomain DNS record on `www` helps guarantee that a visitor who types `www.` in front of your domain address can still find your website or application.

## Subdomain records

To host content on a subdomain of your domain, first ensure that your [hosting provider](https://developers.cloudflare.com/fundamentals/manage-domains/#host-your-domain) can serve content for the given hostname (`<subdomain>.example.com`).

Then, you would create a corresponding [IP address resolution record](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#ip-address-resolution) (`A`, `AAAA`, or `CNAME`), specifying the label for your subdomain (`blog`, `www`, or `store`, for example) as the record **Name**.

| Type | Name | IPv4 address | Proxy status |
| ---- | ---- | ------------ | ------------ |
| A    | blog | 192.0.2.1    | Proxied      |

* [ Dashboard ](#tab-panel-7953)
* [ API ](#tab-panel-7954)

1. In the Cloudflare dashboard, go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. Select **Add record**.
3. Select `A`, `AAAA`, or `CNAME` as the record **Type**, according to your needs:  
   * To point to an IPv4 address, select `A`, use your subdomain (`blog`) for the record **Name**, and insert the IPv4 address in the respective field.  
   * To point to an IPv6 address, select `AAAA`, use your subdomain (`blog`) for the record **Name**, and insert the IPv6 address in the respective field.  
   * To point to a [fully qualified domain name (FQDN) ↗](https://en.wikipedia.org/wiki/Fully%5Fqualified%5Fdomain%5Fname) (such as `your-site.host.example.com`), select `CNAME`, use your subdomain (`blog`) for the record **Name**, and insert the fully qualified domain name in the **Target** field.
4. Specify the [**Proxy status**](https://developers.cloudflare.com/dns/proxy-status/) and [**TTL**](https://developers.cloudflare.com/dns/manage-dns-records/reference/ttl/) according to your needs.
5. Select **Save** to confirm.

Use the [Create DNS Record API endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/).

For field definitions, refer to the [API documentation](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) (visible once you select the record type under the request body specification).

* To point to an IPv4 address, select **A Record**, use your subdomain (`blog`) for the field `name`, and use the IPv4 address for the field `content`.
* To point to an IPv6 address, select **AAAA Record**, use your subdomain (`blog`) for the field `name`, and use the IPv6 address for the field `content`.
* To point to a [fully qualified domain name (FQDN) ↗](https://en.wikipedia.org/wiki/Fully%5Fqualified%5Fdomain%5Fname) (such as `your-site.host.example.com`), select **CNAME Record**, use your subdomain (`blog`) for the field `name`, and use the fully qualified domain name for the field `content`.

## Subdomain redirects

For more guidance on redirecting a subdomain — either to your main domain or another location — refer to [Set up subdomain redirects](https://developers.cloudflare.com/fundamentals/manage-domains/manage-subdomains/#set-up-redirects).

## SSL/TLS for subdomains

While DNS is what communicates where your website or application can be reached, SSL/TLS is what enables websites and applications to establish connections in a secure way.

If your subdomains are not correctly covered by an SSL/TLS certificate, your visitors will find a warning on their browser stating that your website or application is not secure.

If your main domain is using Cloudflare's [Universal SSL certificate](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/), that certificate also covers all first-level subdomains (`blog.example.com`).

For deeper subdomains (`dev.blog.example.com`), use a [different type of certificate](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/limitations/#full-setup).

Proxy status

Cloudflare can only serve an SSL/TLS certificate for a DNS record when you set the record's [proxy status](https://developers.cloudflare.com/dns/proxy-status/) to **Proxied**. If you do not do this, the origin server your record points to will be responsible for supporting SSL/TLS connections.

## Customize subdomain behavior

If you want to customize Cloudflare settings for individual subdomains, your approach will vary depending on your plan.

Enterprise customers can set up custom settings and access for a specific subdomain within Cloudflare with [Subdomain support](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/).

All other customers can set up subdomain-specific [Configuration Rules](https://developers.cloudflare.com/rules/configuration-rules/) or [Page Rules](https://developers.cloudflare.com/rules/page-rules/) to alter Cloudflare settings.

If you want a subdomain's DNS settings managed totally outside of Cloudflare — meaning this subdomain can be managed by individuals without access to your Cloudflare account — refer to [Delegating subdomains outside of Cloudflare](https://developers.cloudflare.com/dns/manage-dns-records/how-to/subdomains-outside-cloudflare/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/how-to/","name":"How to"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/how-to/create-subdomain/","name":"Create subdomain records"}}]}
```

---

---
title: Create zone apex record
description: Create a DNS record for your zone apex.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Create zone apex record

When you add a domain to Cloudflare, you may also need to create or review the DNS record on your zone apex. Zone apex refers to the domain (`example.com`) or subdomain (`blog.example.com`) that you are [adding to Cloudflare](https://developers.cloudflare.com/dns/concepts/#zone).

Usually, the zone apex record makes your domain accessible by visitors. In this case, the necessary record type ([A, AAAA, or CNAME](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#ip-address-resolution)) and its content will depend on the provider that [hosts](https://developers.cloudflare.com/fundamentals/manage-domains/#host-your-domain) your website or application. If you are using Cloudflare Pages, refer to [Custom domains](https://developers.cloudflare.com/pages/configuration/custom-domains/). If you are using other providers, look for their guidance on how to connect domains managed on external DNS services.

### ANAME or ALIAS

ANAME or ALIAS are DNS records used by specific DNS providers. If your previous provider was using ANAME or ALIAS, you can recreate these records on Cloudflare as CNAME records. Cloudflare's [CNAME flattening](https://developers.cloudflare.com/dns/cname-flattening/)[1](#user-content-fn-1) allows you to create CNAME records at your [zone apex](https://developers.cloudflare.com/dns/concepts/#zone-apex), removing the need for those other record types.

## Footnotes

1. A process in which Cloudflare returns an IP address instead of the target hostname that a CNAME record points to. [↩](#user-content-fnref-1)

## Zone apex record

To create a zone apex record, use `@` for the record **Name**, as in the following example.

| Type | Name | IPv4 address | Proxy status |
| ---- | ---- | ------------ | ------------ |
| A    | @    | 192.0.2.1    | Proxied      |

* [ Dashboard ](#tab-panel-7955)
* [ API ](#tab-panel-7956)

1. In the Cloudflare dashboard, go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. Select **Add record**.
3. Select `A`, `AAAA`, or `CNAME` as the record **Type**, according to your needs:  
   * To point to an IPv4 address, select `A`, use your zone apex (`@`) for the record **Name**, and insert the IPv4 address in the respective field.  
   * To point to an IPv6 address, select `AAAA`, use your zone apex (`@`) for the record **Name**, and insert the IPv6 address in the respective field.  
   * To point to a [fully qualified domain name (FQDN) ↗](https://en.wikipedia.org/wiki/Fully%5Fqualified%5Fdomain%5Fname) (such as `your-site.host.example.com`), select `CNAME`, use your zone apex (`@`) for the record **Name**, and insert the fully qualified domain name in the **Target** field.
4. Specify the [**Proxy status**](https://developers.cloudflare.com/dns/proxy-status/) and [**TTL**](https://developers.cloudflare.com/dns/manage-dns-records/reference/ttl/) according to your needs.
5. Select **Save** to confirm.

Use the [Create DNS Record API endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/).

For field definitions, refer to the [API documentation](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) (visible once you select the record type under the request body specification).

* To point to an IPv4 address, select **A Record**, use your zone apex (`@`) for the field `name`, and use the IPv4 address for the field `content`.
* To point to an IPv6 address, select **AAAA Record**, use your zone apex (`@`) for the field `name`, and use the IPv6 address for the field `content`.
* To point to a [fully qualified domain name (FQDN) ↗](https://en.wikipedia.org/wiki/Fully%5Fqualified%5Fdomain%5Fname) (such as `your-site.host.example.com`), select **CNAME Record**, use your zone apex (`@`) for the field `name`, and use the fully qualified domain name for the field `content`.

## Domain redirects

Once you create a domain, you may want to route that traffic to other places.

For more guidance, refer to [Redirect domain to subdomain](https://developers.cloudflare.com/fundamentals/manage-domains/manage-subdomains/#redirect-the-apex-domain-to-a-subdomain) or [Redirect one domain to another](https://developers.cloudflare.com/fundamentals/manage-domains/redirect-domain/).

## Get free SSL certificates

While DNS is what communicates where your website or application can be reached, SSL/TLS is what enables websites and applications to establish connections in a secure way.

If your domain is not correctly covered by an SSL/TLS certificate, your visitors will find a warning on their browser stating that your website or application is not secure.

Cloudflare offers free, unshared, publicly trusted [Universal SSL certificates](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) to all Cloudflare domains.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/how-to/","name":"How to"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/how-to/create-zone-apex/","name":"Create zone apex record"}}]}
```

---

---
title: Set up email records
description: Configure MX, SPF, DKIM, and DMARC records for email.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Set up email records

There are three reasons to set up email records for your domain:

* To make sure your domain can [receive email](#receive-email).
* To make sure your domain can [send and receive email](#send-and-receive-email).
* To prevent other email senders from [spoofing your domain](#prevent-domain-spoofing).

The exact values for your DNS mail records depend on your email provider. If you have issues, review the [Troubleshooting](https://developers.cloudflare.com/dns/troubleshooting/email-issues/) and contact your email service provider to confirm your DNS records are correct.

---

## Receive email

If you only need to **receive** emails, Cloudflare offers [Email Routing](https://developers.cloudflare.com/email-service/) for free email forwarding to custom email addresses.

## Send and receive email

To **send and receive** emails from your domain, you need an SMTP provider. Then, create two DNS records within Cloudflare, following the steps below:

1. Get the IP address and MX record details from your SMTP provider ([vendor-specific guidelines](https://developers.cloudflare.com/dns/manage-dns-records/reference/vendor-specific-records/)).
2. [Add an A or AAAA record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) for your mail subdomain that points to the IP address of your mail server.  
| **Type** | **Name** | **IPv4 address** | **Proxy status** |  
| -------- | -------- | ---------------- | ---------------- |  
| A        | mail     | 192.0.2.1        | DNS only         |  
API example  
Required API token permissions  
At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:  
   * `DNS Write`  
Create DNS Record  
```  
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \  
  --request POST \  
  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \  
  --json '{  
    "type": "A",  
    "name": "mail.example.com",  
    "content": "192.0.2.1",  
    "ttl": 3600,  
    "proxied": false  
  }'  
```  
Response  
```  
{  
  "result": {  
    "id": "<ID>",  
    "zone_id": "<ZONE_ID>",  
    "zone_name": "example.com",  
    "name": "mail.example.com",  
    "type": "A",  
    "content": "192.0.2.1",  
    "proxiable": true,  
    "proxied": false,  
    "ttl": 3600,  
    "locked": false,  
    "meta": {  
      "source": "primary"  
    },  
    "comment": null,  
    "tags": [],  
    "created_on": "2023-01-17T20:37:05.368097Z",  
    "modified_on": "2023-01-17T20:37:05.368097Z"  
  },  
  "success": true,  
  "errors": [],  
  "messages": []  
}  
```
3. [Add an MX record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) that points to that subdomain.  
| **Type** | **Name** | **Mail server**  | **TTL** | **Priority** |  
| -------- | -------- | ---------------- | ------- | ------------ |  
| MX       | @        | mail.example.com | Auto    | 5            |  
API example  
Required API token permissions  
At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:  
   * `DNS Write`  
Create DNS Record  
```  
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \  
  --request POST \  
  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \  
  --json '{  
    "type": "MX",  
    "name": "example.com",  
    "content": "mail.example.com",  
    "priority": 5,  
    "ttl": 3600  
  }'  
```  
Response  
```  
{  
  "result": {  
    "id": "<ID>",  
    "zone_id": "<ZONE_ID>",  
    "zone_name": "example.com",  
    "name": "example.com",  
    "type": "MX",  
    "content": "mail.example.com",  
    "priority": 5,  
    "proxiable": false,  
    "proxied": false,  
    "ttl": 3600,  
    "locked": false,  
    "meta": {  
      "source": "primary"  
    },  
    "comment": null,  
    "tags": [],  
    "created_on": "2023-01-17T20:54:23.660869Z",  
    "modified_on": "2023-01-17T20:54:23.660869Z"  
  },  
  "success": true,  
  "errors": [],  
  "messages": []  
}  
```

Note

If you encounter issues with your email setup, refer to our [troubleshooting guide](https://developers.cloudflare.com/dns/troubleshooting/email-issues/).

---

## Prevent domain spoofing

Without email authentication records, anyone can send email that appears to come from your domain — a technique known as domain spoofing. To prevent this, you add DNS TXT records (text-based entries in your domain's DNS settings) that allow receiving mail servers to verify whether an email actually came from you:

* [Sender Policy Framework (SPF) ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/): Lists the IP addresses and domains authorized to send email on behalf of your domain.
* [DomainKeys Identified Mail (DKIM) ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/): Authenticates the sender's domain and verifies that email content was not altered in transit, using a cryptographic signature.
* [Domain-based Message Authentication Reporting and Conformance (DMARC) ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-dmarc-record/): Tells receiving servers what to do when SPF or DKIM checks fail (for example, reject or quarantine the email), and sends you aggregate reports about your email traffic.

Note

For additional background on email security records, refer to the [introductory blog post ↗](https://blog.cloudflare.com/tackling-email-spoofing/).

### Configure email security records

Refer to [Security records](https://developers.cloudflare.com/dmarc-management/security-records/) to learn how to set up your email security records.

## Proxy SMTP traffic

By default, Cloudflare does not proxy email traffic on port 25 (SMTP). You can only proxy outgoing email if you have [Spectrum](https://developers.cloudflare.com/spectrum/) configured for [SMTP](https://developers.cloudflare.com/spectrum/reference/configuration-options/#smtp).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/how-to/","name":"How to"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/how-to/email-records/","name":"Set up email records"}}]}
```

---

---
title: Import and export records
description: Import and export DNS records using zone files.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Import and export records

Use import and export to have more control over your DNS records and make processes like migrating a domain or bulk editing [record comments](https://developers.cloudflare.com/dns/manage-dns-records/reference/record-attributes/) easier.

## Import records

### Limits

* The zone file size limit is 256 KiB (262144 bytes).
* The API rate limit is three requests per minute per user.

### Format your zone file

Create a [BIND zone file ↗](https://en.wikipedia.org/wiki/Zone%5Ffile) for your domain. If you need help, use a [third-party tool ↗](https://pgl.yoyo.org/as/bind-zone-file-creator.php).

If you are using certain record types — for example, `CNAME`, `DNAME`, `MX`, `NS`, `PTR`, or `SRV` records — make sure that the **content** of those records contains fully qualified domain names ending in a trailing period (as in `example.com.`). For more details, refer to [RFC 1035 ↗](https://www.rfc-editor.org/rfc/rfc1035#section-5.1) or this [post on Stack Exchange ↗](https://superuser.com/questions/348282/fqdn-format-in-bind-zone#348284).

### Import zone file to Cloudflare

* [ Dashboard ](#tab-panel-7957)
* [ API ](#tab-panel-7958)

To import a zone file using the dashboard:

1. In the Cloudflare dashboard, go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. Select **Import and Export**.
3. For **Import DNS records**, select your [formatted file](#format-your-zone-file).
4. If you do not want [applicable records](https://developers.cloudflare.com/dns/proxy-status/) proxied, unselect **Proxy imported DNS records**.

To import records using the API, send a [POST request](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/import/) with a properly [formatted file](#format-your-zone-file).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Import DNS Records

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/import" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --form "file=@your_formatted_file.txt"


```

---

## Export records

You can also bulk export records from Cloudflare.

* [ Dashboard ](#tab-panel-7959)
* [ API ](#tab-panel-7960)

To export records using the dashboard:

1. In the Cloudflare dashboard, go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. Select **Import and Export**.
3. Select **Export**.

To export records using the API, send a [GET request](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/export/).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Read`
* `DNS Write`

Export DNS Records

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/export" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

---

## DNS record attributes

When exporting or importing a zone file, Cloudflare formats [comments and tags](https://developers.cloudflare.com/dns/manage-dns-records/reference/record-attributes/) using the following structure, appending the attributes as inline comment using the `;` character after each record in accordance with [RFC 1035 section 5 ↗](https://datatracker.ietf.org/doc/html/rfc1035#section-5-1):

| Combination           | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Only tags**         | Tag names contain a [small set](https://developers.cloudflare.com/dns/manage-dns-records/reference/record-attributes/#tags) of characters.Additionally, tag values must be contained by a double quote (") if they contain ", \=, ,, or \\. When enclosed within double quotes ("), tag values are represented as JSON strings, so other quotes within the value can be escaped as \\".A tag with an empty value can be represented either as my-tag-name:"", my-tag-name:, or my-tag-name. |
| **Only a comment**    | Comments have [fewer limitations](https://developers.cloudflare.com/dns/manage-dns-records/reference/record-attributes/#comments) on characters, meaning that the comment is included verbatim.If the comment includes the string cf\_tags=, you need to include an additional  cf\_tags= at the end of the line.                                                                                                                                                                           |
| **Comment and tags**  | The zone file comment would be of the form ; <comment> cf\_tags=<tags>, as described above. Note the added space character before cf\_tags=.                                                                                                                                                                                                                                                                                                                                                |
| **Neither attribute** | The comment in the zone file may be empty or omitted entirely. Comments in the zone file that do not immediately follow a record are also ignored.                                                                                                                                                                                                                                                                                                                                          |

Example zone file

```

; Only tags

a.example.com.  60  IN  A   1.1.1.1 ;   cf_tags=awesome

b.example.com.  60  IN  A   1.1.1.1 ;   cf_tags=tag1,tag2:value2,tag3:"value,with,commas",tag4:"value with \"escaped\" quotation marks"


; Only a comment

c.example.com.  60  IN  A   1.1.1.1 ; just a comment without tags

d.example.com.  60  IN  A   1.1.1.1 ; this comment contains cf_tags= as text cf_tags=


; Comments and tags

e.example.com.  60  IN  A   1.1.1.1 ; simple example cf_tags=important,ticket:THIS-12345

f.example.com.  60  IN  A   1.1.1.1 ; this is the comment cf_tags=tag1:value1,tag2:value2,tag-without-value,another-tag-without-value,tag-with-quoted-value:"because of the comma, quotes are needed"


; Neither attribute

g.example.com.  60  IN  A   1.1.1.1


```

### Reserved cf- tags

When exporting and importing, special tags starting by `cf-` allow you to control specific Cloudflare configurations. On export, these tags are automatically added to reflect the current configuration for each record on your zone.

Records with cf- tags example

```

;; CNAME Records

a.cloudflaredocs.com.  1  IN  CNAME  example.com. ; cf_tags=test:1,cf-flatten-cname

b.cloudflaredocs.com.  1  IN  CNAME  example.com. ; cf_tags=cf-proxied:false

c.cloudflaredocs.com.  1  IN  CNAME  example.com. ; cf_tags=tag-without-value,cf-proxied:true


```

#### cf-proxied

On export, [proxied DNS records](https://developers.cloudflare.com/dns/proxy-status/) will present a tag `cf-proxied:true` while DNS-only records will have this tag set to `cf-proxied:false`.

When importing zone files, the value in the `cf-proxied` tag will take precedence in determining whether a record should be proxied. This means that:

* If the tag is present, its value will be considered for the respective record regardless of the **Proxy imported DNS records** option being selected (via dashboard), or the `proxied` parameter being generally set to `true` or `false` (via API).
* If the tag is absent, the proxied status will fall back to the general import option, meaning **Proxy imported DNS records** selected or not (via dashboard) or the `proxied` parameter set to `true` or `false` (via API).

#### cf-flatten-cname

If you are on a paid zone and want to use [Per-record CNAME flattening](https://developers.cloudflare.com/dns/cname-flattening/set-up-cname-flattening/#per-record), use the tag `cf-flatten-cname` next to each flattened CNAME record in your zone file. On export, this tag is automatically added to reflect the record configuration that you have on your zone.

## DNS zone file directives

A DNS zone file can be constructed using directives in addition to resource records (RRs). Directives start with `$` and are standardized - `$ORIGIN` and `$INCLUDE` are defined in [RFC 1035 ↗](https://www.rfc-editor.org/rfc/rfc1035#section-5.1), and `$TTL` is defined in [RFC 2308 ↗](https://www.rfc-editor.org/rfc/rfc2308). Additionally, BIND provides the [non-standard ↗](https://bind9.readthedocs.io/en/latest/chapter3.html#bind-primary-file-extension-the-generate-directive) `$GENERATE` directive.

Cloudflare supports `$ORIGIN`, `$TTL`, and `$GENERATE` directives.

`$INCLUDE` is not supported. When a zone file contains a `$INCLUDE` directive, Cloudflare responds with a parsing error `$INCLUDE directive not allowed`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/how-to/","name":"How to"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/how-to/import-and-export/","name":"Import and export records"}}]}
```

---

---
title: Dynamically update DNS records
description: Update DNS records automatically for dynamic IP addresses.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Dynamically update DNS records

Most Internet service providers and some hosting providers dynamically update their customer's IP addresses. If this situation applies to you, you need an automated solution to dynamically update your DNS records in Cloudflare.

## Cloudflare API

Create a script to monitor IP address changes and then have that script push changes to the [Cloudflare API](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/update/).

## ddclient

[ddclient ↗](https://github.com/ddclient/ddclient) is a third-party Perl client used to update dynamic DNS entries for accounts on various DNS providers.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/how-to/","name":"How to"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/how-to/managing-dynamic-ip-addresses/","name":"Dynamically update DNS records"}}]}
```

---

---
title: Round-robin DNS
description: Distribute traffic across multiple origins with round-robin DNS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Round-robin DNS

To randomly distribute traffic across multiple servers, set up multiple DNS `A` or `AAAA` records for the same hostname.

Use this setup for simple, [round-robin load balancing ↗](https://www.cloudflare.com/learning/dns/glossary/round-robin-dns/). If you need more fine-grained control over traffic distribution — including automatic failover, intelligent routing, and more — set up our [add-on load balancing service](https://developers.cloudflare.com/load-balancing/).

## Example scenario

The following example illustrates how you would distribute traffic intended for `www.example.com`. Though the example uses `A` records, you could also use `AAAA` records.

After [creating an account](https://developers.cloudflare.com/fundamentals/account/create-account/) and [updating your nameservers](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/) for `example.com`, you might [create multiple subdomain DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) for `www`:

| Type | Name | IPv4 address |
| ---- | ---- | ------------ |
| A    | www  | 192.0.2.1    |
| A    | www  | 192.0.2.2    |
| A    | www  | 192.0.2.3    |

The exact behavior of your DNS routing would depend on the [proxy status](https://developers.cloudflare.com/dns/proxy-status/) of each record.

### All records unproxied

If all associated records were unproxied, any request to Cloudflare's nameservers would return the three `A` records you previously added.

Each client (oftentimes a browser), would decide which IP address to send the request to. If one IP address fails, the client would choose another option. All requests would be sent directly to the origin server (either `192.0.2.1`, `192.0.2.2`, or `192.0.2.3`, using the example above).

### All records proxied (recommended)

If all associated records were proxied, any request to Cloudflare's nameservers would return two `A` records from Cloudflare's list of IP addresses.

Each client (oftentimes a browser) would decide which Cloudflare IP address to send the request to. Cloudflare would then receive that request and — if Cloudflare needed to contact your origin server — we would pick one of the three IP addresses specified in your DNS records (either `192.0.2.1`, `192.0.2.2`, or `192.0.2.3`, using the example above).

Beyond reducing requests to your origin server, this setup allows your application to take advantage of Cloudflare's [Zero downtime failover](https://developers.cloudflare.com/fundamentals/security/protect-your-origin-server/#zero-downtime-failover). When a request to one IP address fails, Cloudflare automatically retries the request to other IP addresses associated with the same hostname. This behavior prevents end users from experiencing downtime.

### Unproxied and proxied records

If you have a mix of proxied and unproxied records associated with the same hostname, requests happen as if you had [all proxied records](#all-records-proxied-recommended).

This approach is not typically recommended because it can lead to unexpected behavior. For example, if you had two unproxied records and one proxied record, Cloudflare would treat all records as proxied. However, if you deleted the single proxied record, your remaining two unproxied records would immediately be treated as unproxied.

We recommend either using all proxied or all unproxied records to avoid surprises when you make changes to your DNS records.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/how-to/","name":"How to"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/how-to/round-robin-dns/","name":"Round-robin DNS"}}]}
```

---

---
title: Delegate subdomains
description: Delegate subdomains to external DNS providers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Delegate subdomains

Subdomain delegation allows different individuals, teams, or organizations to manage different subdomains of a site.

Note

DNS delegation is not possible for Cloudflare domains using a [CNAME setup (partial)](https://developers.cloudflare.com/dns/zone-setups/partial-setup).

For instance, consider `example.com` as a Cloudflare domain with `www.example.com` managed in Cloudflare's **DNS** app and `blog.example.com` delegated to nameservers outside of Cloudflare. In this example, `blog.example.com` can now be managed by individuals who do not have access to Cloudflare credentials for the `example.com` domain.

Warning

Cloudflare's CDN and security services are not applied to delegated subdomains.

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

---

## Delegate a subdomain (outgoing)

To delegate a subdomain such as `blog.example.com`, tell DNS resolvers where to find the zone file:

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com) and select your account.
2. Select the domain that contains the subdomain to be delegated.
3. Go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
4. Create `NS` records for the subdomain. For example:  
   * `blog.example.com NS ns1.externalhost.com`  
   * `blog.example.com NS ns2.externalhost.com`  
   * `blog.example.com NS ns3.externalhost.com`  
Note  
The `A` records for the subdomain are only required as glue records for nameservers that are located in the subdomain of the current zone that is being delegated.
5. (Optional) If the delegated nameserver has DNSSEC enabled, [add the DS record](https://developers.cloudflare.com/dns/dnssec/#1-activate-dnssec-in-cloudflare) in Cloudflare.

### Limits

When creating NS records, there are limits on the number of nameservers that can be associated with a single delegation name.

According to DNS standards defined in [RFC 1912 ↗](https://www.rfc-editor.org/rfc/rfc1912.html), a delegation should not include more than seven nameserver names for the same delegation name.

To align with these standards and maintain platform stability:

* Cloudflare supports up to 10 NS records per delegation name, but the best practice is to keep the set at seven or fewer.
* Creating more than 10 NS records for the same name is not supported. Requests that exceed this limit may be rejected or fail validation.

Example

DNS management for **example.com**:

| Type | Name | Content               |
| ---- | ---- | --------------------- |
| NS   | blog | ns1.externalhost.com  |
| NS   | blog | ns2.externalhost.com  |
| NS   | blog | ns3.externalhost.com  |
| NS   | blog | ns4.externalhost.com  |
| NS   | blog | ns5.externalhost.com  |
| NS   | blog | ns6.externalhost.com  |
| NS   | blog | ns7.externalhost.com  |
| NS   | blog | ns8.externalhost.com  |
| NS   | blog | ns9.externalhost.com  |
| NS   | blog | ns10.externalhost.com |

In this example, Cloudflare would prevent you from adding another NS record for the delegation name `blog`.

## Delegate a subdomain (incoming)

To delegate a subdomain from an external DNS provider to Cloudflare, refer to [subdomain setups](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/setup/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/how-to/","name":"How to"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/how-to/subdomains-outside-cloudflare/","name":"Delegate subdomains"}}]}
```

---

---
title: DNS record types
description: DNS record types supported by Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNS record types

This page provides information about some of the different types of DNS records that you can manage on Cloudflare. For guidance on how to add, edit, or delete DNS records, refer to [Manage DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/).

Note

Each DNS record has a maximum wire format size of 4,096 bytes. Wire format refers to how a record is encoded when transmitted over the DNS protocol ([RFC 1035 ↗](https://www.rfc-editor.org/rfc/rfc1035.html#section-3.2.1)).

If you have multiple records with the same name and type, their combined content length must not exceed 8,192 characters.

---

## IP address resolution

At least one **IP address resolution** record is required for each domain on Cloudflare. These records are the only ones you can [proxy](https://developers.cloudflare.com/dns/proxy-status/) through Cloudflare.

### A and AAAA

[A and AAAA records ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-a-record/) map a domain name to one or multiple IPv4 or IPv6 address(es).

These records include the following fields:

* **Name**: A subdomain or the zone apex (`@`).  
   * The name must be composed of labels of 63 characters or less (`label1.label2.label3`), where the fully qualified domain name (`label1.label2.label3.example.com`) does not exceed 253 characters.  
   * DNS labels can contain any octet (byte value). However, for compatibility with hostnames and TLS certificates, it is recommended to use only letters, digits, and hyphens (LDH rule). This is not a DNS protocol requirement, meaning DNS will work even if you do not follow these conventions.  
   * There is no requirement to start with a letter or end with a letter or digit.  
   * Underscores are valid in DNS and commonly used for service records.
* **IPv4/IPv6 address**: Your origin server address (cannot be a [Cloudflare IP ↗](https://www.cloudflare.com/ips))

Note

Cloudflare uses the [canonical notation ↗](https://www.rfc-editor.org/rfc/rfc5952.html#section-4.2) to store DNS records. This means that an AAAA record with content `fe80::0:0:1` is stored and returned as `fe80::1`, for example.

Alternative notations of IPv4 addresses (`1.1` for `1.0.0.1`, for example) are not supported for A records.

* **TTL**: Time to live, which controls how long DNS resolvers should cache a response before revalidating it.  
   * If the **Proxy Status** is **Proxied**, this value defaults to **Auto**, which is 300 seconds.  
   * If the **Proxy Status** is **DNS Only**, you can customize the value.
* **Proxy status**: For more details, refer to [Proxied DNS records](https://developers.cloudflare.com/dns/proxy-status/).
* **Private network routing**: Some Enterprise customers also have access to [private network routing](https://developers.cloudflare.com/dns/private-origins/private-network-routing/). For `A` and `AAAA` records, this feature allows you to proxy HTTP/HTTPS traffic from public hostnames to origins in your private network.

#### Example API call

When creating A or AAAA records [using the API](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records):

* The `content` of the records is an IP address (IPv4 for A or IPv6 for AAAA).
* The `proxied` field affects the record's [proxy status](https://developers.cloudflare.com/dns/proxy-status/).

For field definitions, refer to the [API documentation](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) (visible once you select the record type under the request body specification).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Create DNS Record

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "type": "A",

    "name": "www.example.com",

    "content": "192.0.2.1",

    "ttl": 3600,

    "proxied": false

  }'


```

Response

```

{

  "result": {

    "id": "<ID>",

    "zone_id": "<ZONE_ID>",

    "zone_name": "example.com",

    "name": "www.example.com",

    "type": "A",

    "content": "192.0.2.1",

    "proxiable": true,

    "proxied": false,

    "ttl": 1,

    "locked": false,

    "meta": {

      "source": "primary"

    },

    "comment": null,

    "tags": [],

    "created_on": "2023-01-17T20:37:05.368097Z",

    "modified_on": "2023-01-17T20:37:05.368097Z"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

### CNAME

[CNAME records ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-cname-record/) map a domain name to another (canonical) domain name. They can be used to resolve other record types present on the target domain name.

These records include the following fields:

* **Name**: A subdomain or the zone apex (`@`).  
   * The name must be composed of labels of 63 characters or less (`label1.label2.label3`), where the fully qualified domain name (`label1.label2.label3.example.com`) does not exceed 253 characters.  
   * DNS labels can contain any octet (byte value). However, for compatibility with hostnames and TLS certificates, it is recommended to use only letters, digits, and hyphens (LDH rule). This is not a DNS protocol requirement, meaning DNS will work even if you do not follow these conventions.  
   * There is no requirement to start with a letter or end with a letter or digit.  
   * Underscores are valid in DNS and commonly used for service records.
\- **Target**: The hostname where traffic should be directed (`example.com`). - **TTL**: Time to live, which controls how long DNS resolvers should cache a response before revalidating it.

* If the **Proxy Status** is **Proxied**, this value defaults to **Auto**, which is 300 seconds. - If the **Proxy Status** is **DNS Only**, you can customize the value. - **Proxy status**: For more details, refer to [Proxied DNS records](https://developers.cloudflare.com/dns/proxy-status/).

#### Proxied CNAME records

Observe the following aspects, especially before changing a CNAME record from [proxied](https://developers.cloudflare.com/dns/proxy-status/) to DNS-only or vice versa:

* If a hostname is meant to proxy traffic, you can use CNAME records to point to other CNAME records (`www.example2.com` \--> `www.example1.com` \--> `www.example.com`), but the final record must point to a hostname with a valid IP address (and therefore a valid A or AAAA record). Also, queries for other record types on the same name are not supported.

Example

DNS management for **example.com**:

| Type  | Name | Content              | Proxy status |
| ----- | ---- | -------------------- | ------------ |
| CNAME | abc  | target.external.test | Proxied      |

DNS management for **external.test**:

| Type | Name   | Content            |
| ---- | ------ | ------------------ |
| A    | target | 192.0.2.1          |
| TXT  | target | "some TXT content" |

In this example, a query for TXT in `abc.example.com` will **not** return the TXT content in the target zone.

* Cloudflare uses a process called CNAME flattening to deliver better performance. This process supports a few features and can interact with [different setups that depend on CNAME records](https://developers.cloudflare.com/dns/cname-flattening/#aspects-to-keep-in-mind). Refer to the [CNAME flattening section](https://developers.cloudflare.com/dns/cname-flattening/) to learn more about this.
* If you encounter a CNAME record that you cannot proxy — usually associated with another CDN provider — a proxied version of that record will cause connectivity errors. Cloudflare is purposely preventing that record from being proxied to protect you from a misconfiguration. Refer to [proxying limitations](https://developers.cloudflare.com/dns/proxy-status/limitations/#proxy-eligibility) for details.

Note

Specific CNAME record values with traffic proxied through Cloudflare will enable O2O routing for the Shopify SaaS provider. Refer to the [Shopify provider guide](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/shopify/) for more information.

#### Example API call

When creating CNAME records [using the API](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records):

* The `content` of the records is a [fully qualified domain name ↗](https://en.wikipedia.org/wiki/Fully%5Fqualified%5Fdomain%5Fname).
* The `proxied` field affects the record's [proxy status](https://developers.cloudflare.com/dns/proxy-status/).

For field definitions, refer to the [API documentation](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) (visible once you select the record type under the request body specification).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Create DNS Record

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "type": "CNAME",

    "name": "www.example.com",

    "content": "www.another-example.com",

    "ttl": 3600,

    "proxied": false

  }'


```

Response

```

{

  "result": {

    "id": "<ID>",

    "zone_id": "<ZONE_ID>",

    "zone_name": "example.com",

    "name": "www.example.com",

    "type": "CNAME",

    "content": "www.another-example.com",

    "proxiable": true,

    "proxied": false,

    "ttl": 1,

    "locked": false,

    "meta": {

      "source": "primary"

    },

    "comment": null,

    "tags": [],

    "created_on": "2023-01-17T20:37:05.368097Z",

    "modified_on": "2023-01-17T20:37:05.368097Z"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

---

## Email authentication

These records are recommended regardless of whether your domain sends email messages. Creating [secure email records ↗](https://blog.cloudflare.com/tackling-email-spoofing/) can help protect your domain against email spoofing.

If your domain is not used to send email messages, learn more about creating recommended [restrictive records ↗](https://www.cloudflare.com/learning/dns/dns-records/protect-domains-without-email/).

### MX

A mail exchange (MX) record is required to deliver email to a mail server.

* [MX record syntax ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-mx-record/)
* [Create an MX record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/email-records/#send-and-receive-email)

For field definitions, refer to the [API documentation](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) (visible once you select the record type under the request body specification).

### DKIM

A DomainKeys Identified Mail (DKIM) record ensures email authenticity by cryptographically signing emails:

* [DKIM record syntax ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/)
* [Create a DKIM record](https://developers.cloudflare.com/dmarc-management/security-records/#create-security-records)

### SPF

A Sender Policy Framework (SPF) record lists authorized IP addresses and domains that can send email on behalf of your domain.

* [SPF record syntax ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/)
* [Create an SPF record](https://developers.cloudflare.com/dmarc-management/security-records/#create-security-records)

### DMARC

A Domain-based Message Authentication Reporting and Conformance (DMARC) record helps generate aggregate reports about your email traffic and provide clear instructions for how email receivers should treat non-conforming emails.

* [DMARC record syntax ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-dmarc-record/)
* [Create a DMARC record](https://developers.cloudflare.com/dmarc-management/security-records/#create-security-records)

---

## Specialized records

### TXT

A [text (TXT) record ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-txt-record/) lets you enter text into the DNS system.

As the content of TXT records consist of one or more text strings delimited by double quotes (`"`), you might find a validation error if you add inconsistent quotation marks (for example, `"this` or `"these" ones"`). For new records, if you save your TXT content without any quotes, Cloudflare will automatically add double quotes. For details, refer to [What is a DNS TXT record ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-txt-record/).

At Cloudflare, TXT records are most commonly used to demonstrate domain ownership prior to issuing SSL/TLS certificates for [your domain](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/) or a [Cloudflare for SaaS domain](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/).

You could also use TXT to create email authentication records, but we recommend that you use our [Email security Wizard](https://developers.cloudflare.com/dns/manage-dns-records/how-to/email-records/#prevent-domain-spoofing) instead.

For field definitions, refer to the [API documentation](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) (visible once you select the record type under the request body specification).

### CAA

A [Certificate Authority Authorization (CAA) record](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/) specifies which Certificate Authorities (CAs) are allowed to issue certificates for a domain.

For field definitions, refer to the [API documentation](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) (visible once you select the record type under the request body specification).

### SRV

A [service record (SRV) ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-srv-record/) specifies a host and port for specific services like voice over IP (VOIP), instant messaging, and more.

#### Example API call

For field definitions, refer to the [API documentation](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) (visible once you select the record type under the request body specification).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Create DNS Record

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "type": "SRV",

    "name": "_xmpp._tcp.example.com",

    "data": {

        "priority": 10,

        "weight": 5,

        "port": 5223,

        "target": "server.example.com"

    }

  }'


```

Response

```

{

  "result": {

    "id": "<ID>",

    "zone_id": "<ZONE_ID>",

    "zone_name": "example.com",

    "name": "_xmpp._tcp.example.com",

    "type": "SRV",

    "content": "5 5223 server.example.com",

    "priority": 10,

    "proxiable": false,

    "proxied": false,

    "ttl": 1,

    "locked": false,

    "data": {

      "port": 5223,

      "priority": 10,

      "target": "server.example.com",

      "weight": 5

    },

    "meta": {

      "auto_added": false,

      "managed_by_apps": false,

      "managed_by_argo_tunnel": false,

      "source": "primary"

    },

    "comment": null,

    "tags": [],

    "created_on": "2022-11-08T15:57:39.585977Z",

    "modified_on": "2022-11-08T15:57:39.585977Z"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

### SVCB and HTTPS

Service Binding (SVCB) and HTTPS Service (HTTPS) records allow you to provide a client with information about how it should connect to a server upfront, without the need of an initial plaintext HTTP connection.

If your domain has [HTTP/2 or HTTP/3 enabled](https://developers.cloudflare.com/speed/optimization/protocol/), [proxied DNS records](https://developers.cloudflare.com/dns/proxy-status/), and is also using [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/), Cloudflare automatically generates HTTPS records on the fly, to advertise to clients how they should connect to your server.

#### Proxied vs DNS-only names

For [proxied (orange cloud)](https://developers.cloudflare.com/dns/proxy-status/) names, Cloudflare synthesizes HTTPS records automatically when Universal SSL is enabled. Manually-added HTTPS records on proxied names are not served — Cloudflare uses the auto-generated records instead.

If you have disabled Universal SSL (for example, because you use [Advanced Certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) exclusively), Cloudflare will not generate HTTPS records for proxied names.

For [DNS-only (grey cloud)](https://developers.cloudflare.com/dns/proxy-status/) names, you can manually add HTTPS records and Cloudflare will serve them. However, **all records with the same name must be DNS-only** for the manual HTTPS record to be served.

Example: Manual HTTPS records and proxy status

For Cloudflare to serve a manually-added HTTPS record, every record with the same name must be DNS-only (grey cloud).

**Will work** — All records with the same name are DNS-only:

| Type  | Name        | Content       | Proxy status |
| ----- | ----------- | ------------- | ------------ |
| A     | example.com | 192.0.2.1     | DNS only     |
| HTTPS | example.com | 1 . alpn="h3" | \-           |

The HTTPS record will be served because the A record is DNS-only.

**Will not work** — Mixed proxy status for the same name:

| Type  | Name        | Content       | Proxy status |
| ----- | ----------- | ------------- | ------------ |
| AAAA  | example.com | 2001:db8::1   | Proxied      |
| HTTPS | example.com | 1 . alpn="h3" | \-           |

The HTTPS record will **not** be served because the AAAA record with the same name is proxied.

For more details and context, refer to the [announcement blog post ↗](https://blog.cloudflare.com/speeding-up-https-and-http-3-negotiation-with-dns/) and [RFC 9460 ↗](https://www.rfc-editor.org/rfc/rfc9460.html).

For field definitions, refer to the [API documentation](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) (visible once you select the record type under the request body specification).

### PTR

A [pointer (PTR) record ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-ptr-record/) specifies the allowed hosts for a given IP address.

Within Cloudflare, PTR records are used for reverse DNS lookups and should preferably be added to [reverse zones](https://developers.cloudflare.com/dns/additional-options/reverse-zones/).

For field definitions, refer to the [API documentation](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) (visible once you select the record type under the request body specification).

### SOA

A start of authority (SOA) record stores information about your domain such as admin email address, when the domain was last updated, and more. Refer to [What is a DNS SOA record ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-soa-record/) for an example.

If you are using Cloudflare for your [authoritative DNS](https://developers.cloudflare.com/dns/zone-setups/full-setup/), you do not need to create an SOA record. Cloudflare creates this record automatically when you start using Cloudflare's authoritative nameservers.

With Enterprise accounts, you also have the option to change the SOA record values that Cloudflare will use:

* As a DNS zone default: Define the SOA record values that Cloudflare will use for all new zones added to your account. Refer to [Configure DNS zone defaults](https://developers.cloudflare.com/dns/additional-options/dns-zone-defaults/) for step-by-step guidance.
* For existing zones: Override the defaults or Cloudflare-generated values under **DNS record options** on the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page.

Refer to the following list for information about each SOA record field:

SOA record fields

* **`MNAME`**: The primary nameserver for the zone. Secondary nameservers receive zone updates from the nameserver specified in this field.
* **`RNAME`**: The email address of the administrator responsible for the zone.  
The `@` symbol is replaced by the first dot. If an email address contains a dot before `@`, this should be represented as `\.`.  
| Email                | RNAME                  |  
| -------------------- | ---------------------- |  
| john@example.com     | john.example.com       |  
| john.doe@example.com | john\\.doe.example.com |
* **`Serial`**: The serial number for the zone. Secondary nameservers initiate zone transfers if this number increases.
* **`Refresh`**: Time (in seconds) after which a secondary nameserver should query the primary for the `SOA` record, to detect zone changes. Only relevant if DNS NOTIFY ([RFC 1996 ↗](https://www.rfc-editor.org/rfc/rfc1996.html)) is not configured.  
| Default | Minimum | Maximum |  
| ------- | ------- | ------- |  
| 10000   | 600     | 86400   |
* **`Retry`**: Time (in seconds) after which a secondary nameserver should retry getting the serial number from the primary nameserver after a failed attempt. Any specified values must not be greater than `Refresh`.  
| Default | Minimum | Maximum |  
| ------- | ------- | ------- |  
| 2400    | 600     | 3600    |
* **`Expire`**: Time (in seconds) after which a secondary nameserver should stop answering queries for a zone if the primary does not respond. Any specified values must not be smaller than `Refresh`.  
| Default | Minimum | Maximum |  
| ------- | ------- | ------- |  
| 604800  | 86400   | 2419200 |
* **`Record TTL`**: The [time to live](https://developers.cloudflare.com/dns/manage-dns-records/reference/ttl/) of the SOA record.  
| Default | Minimum | Maximum |  
| ------- | ------- | ------- |  
| 3600    | 1800    | 3600    |
* **`Minimum TTL`**: The TTL for caching negative responses. Refer to [RFC 2308 ↗](https://www.rfc-editor.org/rfc/rfc2308.html#section-4) for details.  
| Default | Minimum | Maximum |  
| ------- | ------- | ------- |  
| 1800    | 60      | 86400   |

Note

When you query the SOA record itself, the TTL in the response is the smaller of the `Record TTL` and the `Minimum TTL` values. For example, if `Record TTL` is `3600` and `Minimum TTL` is `1800`, the SOA record is returned with a TTL of `1800`.

### NS

A [nameserver (NS) record ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-ns-record/) indicates which server should be used for authoritative DNS.

You only need to add NS records to your DNS records table in Cloudflare when you are using [subdomain setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/) or [delegating subdomains outside of Cloudflare](https://developers.cloudflare.com/dns/manage-dns-records/how-to/subdomains-outside-cloudflare/).

For field definitions, refer to the [API documentation](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) (visible once you select the record type under the request body specification).

Note

Your assigned Cloudflare nameservers, custom nameservers, and their corresponding [nameserver TTLs](https://developers.cloudflare.com/dns/nameservers/nameserver-options/#nameserver-ttl) are controlled via dedicated sections on the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page. For details, refer to [Nameservers](https://developers.cloudflare.com/dns/nameservers/).

#### Limits

When creating NS records, there are limits on the number of nameservers that can be associated with a single delegation name.

According to DNS standards defined in [RFC 1912 ↗](https://www.rfc-editor.org/rfc/rfc1912.html), a delegation should not include more than seven nameserver names for the same delegation name.

To align with these standards and maintain platform stability:

* Cloudflare supports up to 10 NS records per delegation name, but the best practice is to keep the set at seven or fewer.
* Creating more than 10 NS records for the same name is not supported. Requests that exceed this limit may be rejected or fail validation.

Example

DNS management for **example.com**:

| Type | Name | Content               |
| ---- | ---- | --------------------- |
| NS   | blog | ns1.externalhost.com  |
| NS   | blog | ns2.externalhost.com  |
| NS   | blog | ns3.externalhost.com  |
| NS   | blog | ns4.externalhost.com  |
| NS   | blog | ns5.externalhost.com  |
| NS   | blog | ns6.externalhost.com  |
| NS   | blog | ns7.externalhost.com  |
| NS   | blog | ns8.externalhost.com  |
| NS   | blog | ns9.externalhost.com  |
| NS   | blog | ns10.externalhost.com |

In this example, Cloudflare would prevent you from adding another NS record for the delegation name `blog`.

### DS and DNSKEY

[DS and DNSKEY ↗](https://www.cloudflare.com/learning/dns/dns-records/dnskey-ds-records/) records help implement DNSSEC, which cryptographically signs DNS records to prevent domain spoofing.

Most Cloudflare domains do not need to add these records and should instead follow our [DNSSEC setup guide](https://developers.cloudflare.com/dns/dnssec/).

For field definitions, refer to the [API documentation](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) (visible once you select the record type under the request body specification).

### Other

Cloudflare also supports other record types that are less common, such as URI, NAPTR, and certificate-related record types (SSHFP, TLSA, SMIMEA, and CERT). Refer to our [blog post ↗](https://blog.cloudflare.com/additional-record-types-available-with-cloudflare-dns/) for more information.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/reference/dns-record-types/","name":"DNS record types"}}]}
```

---

---
title: Record attributes
description: Attributes and metadata for DNS records.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Record attributes

Use DNS record comments and tags to categorize and clarify the purpose of DNS records within Cloudflare.

Comments provide a unique descriptions for specific records, whereas tags group similar records into categories.

These attributes are particularly useful when:

* Multiple teams are managing DNS records within the same zone.
* Your zone contains a large number of DNS records.
* You want to filter your DNS records based on matching attributes (for example, when they are managed by the same team or used for the same application).

Note

The information in record attributes will not impact DNS record resolution or propagation timing and is only meant for your private reference. This information is only visible to [members](https://developers.cloudflare.com/fundamentals/manage-members/manage/) of your Cloudflare account and is not visible publicly.

---

## Availability

Comments and tags are only supported for [primary zones (full setup)](https://developers.cloudflare.com/dns/zone-setups/full-setup/) and [partial zones (CNAME setup)](https://developers.cloudflare.com/dns/zone-setups/partial-setup/).

### Record comments

| Free                | Pro | Business | Enterprise |     |
| ------------------- | --- | -------- | ---------- | --- |
| Availability        | Yes | Yes      | Yes        | Yes |
| Character limit     | 100 | 500      | 500        | 500 |
| Comments per record | 1   | 1        | 1          | 1   |

### Record tags

| Free                                               | Pro | Business | Enterprise |     |
| -------------------------------------------------- | --- | -------- | ---------- | --- |
| Availability                                       | No  | Yes      | Yes        | Yes |
| Name character limit (everything before the colon) | N/A | 32       | 32         | 32  |
| Value character limit (everything after the colon) | N/A | 100      | 100        | 100 |
| Tags per record                                    | N/A | 20       | 20         | 20  |

---

## Add or edit record attributes

Create or edit record attributes just like any other aspect of DNS records, whether through the [dashboard](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) or [API](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/).

You can also add or edit attributes by [exporting and re-importing](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/#dns-record-attributes) your records, or using the [Batch record changes API](https://developers.cloudflare.com/dns/manage-dns-records/how-to/batch-record-changes/#use-the-api).

When exporting and importing, special tags starting by `cf-` allow you to control specific Cloudflare configurations. On export, these tags are automatically added to reflect the current configuration for each record on your zone. Refer to [reserved cf- tags](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/#reserved-cf--tags) for details.

---

## Reference

### Comments

Comments are treated as [graphic Unicode characters ↗](https://en.wikipedia.org/wiki/Graphic%5Fcharacter), meaning that they are case-sensitive and do not have any character limitations. However, comments do not support newline (`\n`) or carriage return (`\r`) characters.

### Tags

Tags are treated as an array of `name:value` pairs, meaning that tag names are not case-sensitive and can only contain letters, numbers, `-`, and `_`. For tag values, the same character restrictions apply as for comments.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/reference/record-attributes/","name":"Record attributes"}}]}
```

---

---
title: Time to Live (TTL)
description: How DNS Time to Live values affect record caching.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Time to Live (TTL)

**Time to Live (TTL)** is a field on [DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) that controls how long each record is cached and — as a result — how long it takes for record updates to reach your end users.

Longer TTLs speed up [DNS lookups ↗](https://www.cloudflare.com/learning/dns/what-is-dns/) by increasing the chance of cached results, but a longer TTL also means that updates to your records take longer to go into effect.

## Proxied records

By default, all [proxied records](https://developers.cloudflare.com/dns/proxy-status/) have a TTL of **Auto**, which is set to 300 seconds. This value cannot be edited.

Since only [records used for IP address resolution](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#ip-address-resolution) can be proxied, this setting ensures that potential changes to the assigned [anycast IP address](https://developers.cloudflare.com/fundamentals/concepts/cloudflare-ip-addresses/) will take effect quickly, as recursive resolvers will not cache them for longer than 300 seconds (five minutes).

Note

It may take longer than 5 minutes for you to actually experience record changes, as your local DNS cache may take longer to update.

## Unproxied records

For **DNS only** records, you can choose a TTL between **30 seconds** (Enterprise) or **60 seconds** (non-Enterprise) and **1 day**.

A TTL of **Auto** is set to 300 seconds (five minutes).

## Nameserver TTL

[Nameserver TTL](https://developers.cloudflare.com/dns/nameservers/nameserver-options/#nameserver-ttl) is a separate feature and only affects Cloudflare nameservers and custom nameservers. For other [NS records](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#ns) on your DNS records table, TTL is controlled by their respective TTL fields.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/reference/ttl/","name":"Time to Live (TTL)"}}]}
```

---

---
title: Vendor-specific DNS records
description: DNS records for common third-party services.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Vendor-specific DNS records

This article requires prior knowledge of DNS record management via the Cloudflare dashboard. To learn more, refer to Cloudflare's article on [managing DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/).

## Google

### Google Workspace MX records

Google Workspace requires [specific MX records ↗](https://support.google.com/a/answer/174125) added to your DNS provider.

Once you [add these records to Cloudflare](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/):

* [Test the configuration ↗](https://toolbox.googleapps.com/apps/checkmx/check)
* Do not add other `MX` records other than those provided by Google.

### Google Workspace service URLs

If you want to customize the service addresses URLs associated with Google Workspace, refer to [Google's documentation ↗](https://support.google.com/a/answer/53340).

Warning

Google enforces HTTPS on its services. If you find errors about redirect loops when browsing to your site through Cloudflare, use Cloudflare's [Full encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full/).

### Google site verification

To add a site verification record in Cloudflare, follow [Google's documentation ↗](https://support.google.com/a/answer/7173990).

---

## Amazon

### Amazon Route53

AWS customers must [update their domain's nameservers ↗](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-name-servers-glue-records.html) to point to their new Cloudflare nameservers.

### Amazon S3 bucket

Find the [URL ↗](https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-bucket-intro.html) for your bucket.

Then, [create a CNAME record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) in Cloudflare. For example, if the full host URL of the bucket is `files.example.com.s3.amazonaws.com`, you would add a `CNAME` record similar to the following:

```

files  CNAME  files.example.com.s3.amazonaws.com


```

Warning

AWS states in their [documentation ↗](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#VirtualHostingCustomURLs) that the CNAME and the bucket name must be the same. To avoid potential compromise if you set it up differently, use a [host header origin rule](https://developers.cloudflare.com/rules/origin-rules/features/#host-header) to explicitly route all requests to the correct bucket.

### Amazon Simple Email Service (SES)

For help setting up DKIM in SES, refer to the [Amazon documentation ↗](https://docs.aws.amazon.com/ses/latest/dg/creating-identities.html).

### Amazon ELB configuration

Refer to [Amazon's ELB help content ↗](http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/DeveloperGuide/using-domain-names-with-elb.html) for guidance on ELB configuration at Amazon, but generally you should:

Add a [CNAME record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) to Cloudflare for the hostname you receive from AWS, for example:

| Type  | Name | Target                                       | Proxy status |
| ----- | ---- | -------------------------------------------- | ------------ |
| CNAME | elb  | <AWS\_HOSTNAME>.<REGION>.\_elb.amazonaws.com | Proxied      |

### Amazon Amplify

To use Cloudflare DNS with AWS Amplify, refer to the [Amplify help content ↗](https://docs.aws.amazon.com/amplify/latest/userguide/to-add-a-custom-domain-managed-by-a-third-party-dns-provider.html) and follow the instructions for **manual configuration**.

At Cloudflare, you will need at least two `CNAME` records:

* A DNS-only `CNAME` to validate your domain ownership, which should look like the following:

| Type  | Name             | Target                                         | Proxy status |
| ----- | ---------------- | ---------------------------------------------- | ------------ |
| CNAME | <UNIQUE\_STRING> | <UNIQUE\_STRING>.mhbtsbpdnt.acm-validation.aws | DNS only     |

CNAME flattening

If your Cloudflare zone is on a paid plan, also make sure that the **Flatten** option turned off for the validation `CNAME` record, and that you zone is **not** using [CNAME flattening for all CNAME records](https://developers.cloudflare.com/dns/cname-flattening/set-up-cname-flattening/#for-all-cname-records).

* One `CNAME` for the apex domain (`example.com`) and/or for each of the subdomains (`blog.example.com`) that you want to manage on Cloudflare. For details refer to [Manage DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/). These records can be proxied.

| Type  | Name | Target                             |
| ----- | ---- | ---------------------------------- |
| CNAME | @    | <AMPLIFY\_HOSTNAME>.cloudfront.net |

| Type  | Name | Target                             |
| ----- | ---- | ---------------------------------- |
| CNAME | blog | <AMPLIFY\_HOSTNAME>.cloudfront.net |

---

## Microsoft

### Microsoft 365

For information about the records to Microsoft 365, refer to [Microsoft's documentation ↗](https://learn.microsoft.com/en-us/microsoft-365/admin/get-help-with-domains/information-for-dns-records).

### Microsoft Azure

Follow Microsoft's instructions on [configuring Azure DNS settings ↗](https://learn.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-custom-domain).

Then, add Azure's required records to [Cloudflare DNS](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/).

---

## Miscellaneous vendors

### ClickFunnels

You can configure Cloudflare to work with ClickFunnels. The process requires updating your Cloudflare DNS settings.

* [Adding a Cloudflare subdomain ↗](https://help.clickfunnels.com/hc/en-us/articles/360005906774-Adding-A-Cloudflare-Subdomain-)
* [Adding a Cloudflare domain ↗](https://help.clickfunnels.com/hc/en-us/articles/360005906094-Cloudflare-CNAME-Record)

### Discourse

To use Discourse with Cloudflare, refer to [Using Discourse with Cloudflare: Best Practices ↗](https://community.cloudflare.com/t/using-discourse-with-cloudflare-best-practices/602890).

### Forward Email

To use Cloudflare with Forward Email, refer to [Forward Email configuration with Cloudflare ↗](https://forwardemail.net/guides/cloudflare).

### Mailchimp

For help with Mailchimp, refer to [Use a custom domain with Mailchimp ↗](https://mailchimp.com/help/connect-domain/).

Note

When you [add records to Cloudflare DNS](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/), those records should be [DNS-only (unproxied)](https://developers.cloudflare.com/dns/proxy-status/#dns-only-records) until Mailchimp verifies your domain. Then, you can switch your DNS records to **Proxied**.

### Ning custom domain

For help with Ning, refer to [Use a custom domain with Ning ↗](https://www.ning.com/help/use-your-own-domain-e-g-example-com-for-your-ning-network/).

Note

When you [add records to Cloudflare DNS](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/), those records should be [DNS-only (unproxied)](https://developers.cloudflare.com/dns/proxy-status/#dns-only-records) until Ning verifies your domain. Then, you can switch your DNS records to **Proxied**.

### Rackspace CloudFiles

Configure Rackspace CloudFiles via _CNAME record_. Consult the [Rackspace documentation ↗](https://docs.rackspace.com/support/how-to/using-cnames-with-cloud-files-containers/).

Refer to Rackspace CloudFiles's documentation to [get a CNAME value ↗](https://docs.rackspace.com/support/how-to/using-cnames-with-cloud-files-containers/), then [add that record within Cloudflare](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/).

Warning

The `CNAME` record needs to be [DNS-only (unproxied)](https://developers.cloudflare.com/dns/proxy-status/#dns-only-records) since rackcdn.com is not compatible with Cloudflare.

### SendGrid

Refer to SendGrid's documentation for how to [make SendGrid compatible with Cloudflare ↗](https://docs.sendgrid.com/ui/sending-email/content-delivery-networks#using-cloudflare).

Note

You may need to refer to Cloudflare's documentation for updated navigation instructions regarding [adding DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) and creating [Configuration rules](https://developers.cloudflare.com/rules/configuration-rules/create-dashboard/).

### SmugMug

For help with SmugMug, refer to [Use a custom domain with SmugMug ↗](https://www.smugmughelp.com/en/articles/363-use-a-custom-domain).

Note

When you [add records to Cloudflare DNS](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/), those records should be [DNS-only (unproxied)](https://developers.cloudflare.com/dns/proxy-status/#dns-only-records) until SmugMug verifies your domain. Then, you can switch your DNS records to **Proxied**.

### Squarespace

First, make sure you [update your nameservers](https://developers.cloudflare.com/dns/zone-setups/full-setup/) and your domain is [active](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/).

Then, set up your Squarespace DNS records:

1. Get your Squarespace DNS information by following [these instructions ↗](https://support.squarespace.com/hc/articles/213469948).
2. In Cloudflare, [add those records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/):  
   * All `A` records should be [Proxied](https://developers.cloudflare.com/dns/proxy-status/)  
   * The `CNAME` record for `www` should also be **Proxied**.  
   * The `CNAME` record for `verify.squarespace.com` should be **DNS-only**.
3. If set up properly, your Squarespace DNS Settings page will now indicate that your 'Settings contain problems.' **This is the expected behavior**.
![Screenshot of error warnings in squarespace](https://developers.cloudflare.com/_astro/hc-import-squarespace_dns_settings-test-2.9_-CHey0_1nttwE.webp) 

#### Pending domain owner verification

The `CNAME` record you added for `verify.squarespace.com` should be **DNS-only**.

If you proxy this record, Squarespace will not be able to verify your domain ownership and show you a `This website is pending domain owner verification` error. To fix the issue, [edit](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#edit-dns-records) the `CNAME` record and change the **Proxy status** to **DNS-only**.

### Tumblr custom domain

Refer to Tumblr's documentation to [get DNS record values ↗](https://help.tumblr.com/hc/en-us/articles/231256548-Custom-Domains). Then, [add records to Cloudflare DNS](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/).

Note

When you [add records to Cloudflare DNS](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/), those records should be [DNS-only (unproxied)](https://developers.cloudflare.com/dns/proxy-status/#dns-only-records) until Tumblr verifies your domain. Then, you can switch your DNS records to **Proxied**.

### Unbounce

Refer to Unbounce's documentation to [get a CNAME value ↗](https://documentation.unbounce.com/hc/en-us/articles/204011950), then [add that record within Cloudflare](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/).

Warning

If Cloudflare is activated via one of our hosting partners, your `CNAME` record should be [DNS-only (unproxied)](https://developers.cloudflare.com/dns/proxy-status/#dns-only-records).

### Wix

You can use Cloudflare with [Wix websites ↗](https://www.wix.com/), though your setup needs to be different than with most website builders.

This is because Wix [does not support ↗](https://support.wix.com/en/article/request-cloudflare-support) using Cloudflare nameservers (which is the normal part of a [primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/) or with domains bought through [Cloudflare Registrar](https://developers.cloudflare.com/registrar/)).

#### Using domain pointing

If you want to manage your DNS through Cloudflare or you bought a domain through [Cloudflare Registrar](https://developers.cloudflare.com/registrar/), you can connect that domain to Wix through [domain pointing ↗](https://support.wix.com/en/article/connecting-a-domain-to-wix-using-the-pointing-method).

This method means your website is using Cloudflare for DNS only, so all your DNS records should be [DNS-only (unproxied)](https://developers.cloudflare.com/dns/proxy-status/#dns-only-records).

### WPEngine

For help configuring WPEngine sites, refer to:

* [Configuring DNS with WPEngine ↗](https://wpengine.com/support/wordpress-best-practice-configuring-dns-for-wp-engine/)
* [Cloudflare best practices ↗](https://wpengine.com/support/cloudflare-best-practices/)

### Zoho

To use Cloudflare with Zoho, refer to [Zoho configuration with Cloudflare ↗](https://www.zoho.com/mail/help/adminconsole/cloudflare.html).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/reference/vendor-specific-records/","name":"Vendor-specific DNS records"}}]}
```

---

---
title: Wildcard DNS records
description: How wildcard DNS records work on Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Wildcard DNS records

Normal DNS records map a domain name to one or multiple IP addresses or other associated resources to a specific domain name (a one-to-many mapping). Wildcard DNS records allow you to have a many-to-many mapping, for example if you had hundreds or thousands of subdomains you wanted to point to the same resources.

Within Cloudflare, wildcard DNS records can be either [proxied or DNS-only](https://developers.cloudflare.com/dns/proxy-status/).

## Create a Wildcard record

To create a wildcard DNS record, [create a DNS record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) with an `*` in the **Name** field.

| Type | Name | IPv4 address | Proxy status |
| ---- | ---- | ------------ | ------------ |
| A    | \*   | 192.0.2.1    | Proxied      |

Warning

If your project is on [Cloudflare Pages](https://developers.cloudflare.com/pages/), note that wildcard custom domains are not supported. Refer to [known issues](https://developers.cloudflare.com/pages/platform/known-issues/#custom-domains) for details.

You can also create a wildcard DNS record specifically for a deeper subdomain. For example, if you wanted to create a wildcard record on `*.www.example.com`, you would create a record with `*.www` in the name field.

| Type  | Name   | IPv4 address | Proxy status |
| ----- | ------ | ------------ | ------------ |
| CNAME | \*.www | example.com  | Proxied      |

### Aspects to consider

#### Wildcards are only supported on the first label

This means that a hostname such as `subdomain.*.example.com` is not a wildcard on the level of the asterisk character. If you create a DNS record with that name, the asterisk is interpreted as the literal character `*` and not as the wildcard operator.

#### Wildcards are multi-level by default

If you create a DNS record on `*.*.example.com`, only the first asterisk is interpreted as a wildcard while the second one is interpreted as the literal `*` character. A record `*.example.com` is already multi-level by default, meaning it would cover `abc.example.com` as well as `123.abc.example.com`, as long as there are no [specific DNS records](#specific-dns-records-take-precedence-over-wildcard-records) that would take precedence.

#### Specific DNS records take precedence over wildcard records

A wildcard record applies only when no exact record exists at the queried name. If a record or delegation exists, the wildcard does not apply.

Example 1 - specific or below

If you have only these two records on your domain:

| Type | Name | Content      |
| ---- | ---- | ------------ |
| A    | \*   | 192.0.2.1    |
| TXT  | abc  | <some\_text> |

The `A` wildcard record will be used for queries going to any subdomain of `example.com` except `abc.example.com` or anything below that specific label (`123.abc.example.com` or `deeper.label.abc.example.com`, and so on).

The wildcard will still be used for deeper labels that are not below the specific record on `abc.example.com` — for example, `deeper.label.xyz.example.com`.

Example 2 - implicit parent

If you have only these two records on your domain:

| Type | Name    | Content      |
| ---- | ------- | ------------ |
| A    | \*      | 192.0.2.1    |
| TXT  | 123.abc | <some\_text> |

In this example, `123.abc.example.com` is a descendant of `abc.example.com`, and `abc.example.com` has no records associated with it. The behavior will depend on the type of nameservers you are using:

* Standard nameservers: The wildcard `*.example.com` will still apply to `abc.example.com`.
* [Advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/setup/)[1](#user-content-fn-1): In compliance with [RFC 4592 ↗](https://www.rfc-editor.org/rfc/rfc4592.html), the wildcard `*.example.com` will not apply to `abc.example.com`.

## Availability

Customers on all plans can create and proxy wildcard DNS records.

## Limitations

If you are using a [CNAME setup (partial)](https://developers.cloudflare.com/dns/zone-setups/partial-setup/) for your DNS, Cloudflare does not automatically provision SSL/TLS certificates for your wildcard record.

For wildcard hostname certificates, certificate issuance and renewal varies based on the type of certificate you are using:

* **Universal**: Perform DCV using [TXT validation method](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/txt/).
* **Advanced**: In most cases, you can opt for [Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/), which greatly simplifies certificate management.

If you cannot use Delegated DCV, you need to use [TXT based DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/txt/) for certificate issuance and renewal. This means you will need to place one TXT DCV token for every hostname on the certificate. If one or more of the hostnames on the certificate fails to validate, the certificate will not be issued or renewed.

This means that a wildcard certificate covering `example.com` and `*.example.com` will require two DCV tokens to be placed at the authoritative DNS provider. Similarly, a certificate with five hostnames in the SAN (including a wildcard) will require five DCV tokens to be placed at the authoritative DNS provider.

## Additional information

For more information on wildcard records — as well as more details about their limitations — refer to the [introductory blog post ↗](https://blog.cloudflare.com/wildcard-proxy-for-everyone/).

## Footnotes

1. An opt-in configuration available for Enterprise customers. [↩](#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":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/reference/wildcard-dns-records/","name":"Wildcard DNS records"}}]}
```

---

---
title: Verify a domain with CNAME
description: Troubleshoot domain verification failures caused by proxied CNAME records, CNAME flattening, or NS record conflicts.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Verify a domain with CNAME

When configuring services from external providers - such as email services, for example - it is possible that they require you to verify your domain by placing a CNAME record at your zone, similar to the following:

```

<value>._domainkey.example.com CNAME <hostname>.<service provider domain>


```

Consider the sections below if this is not working correctly for you.

## Causes

You may find issues if you have one of the following:

* The CNAME record you created for domain verification is set to [**Proxied**](https://developers.cloudflare.com/dns/proxy-status/).
* The CNAME record is correctly set to DNS only (not proxied) but, in your [zone settings ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings), [**CNAME flattening for all CNAME records**](https://developers.cloudflare.com/dns/cname-flattening/set-up-cname-flattening/#for-all-cname-records) is on.
* The CNAME record is correctly set to DNS only (not proxied) but CNAME flattening is set [for that record specifically](https://developers.cloudflare.com/dns/cname-flattening/set-up-cname-flattening/#per-record).
* An [NS record ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-ns-record/) exists, causing a different DNS provider to be authoritative for the subdomain.

## Solution

Make sure that:

* In your zone DNS settings: [**CNAME flattening for all CNAME records**](https://developers.cloudflare.com/dns/cname-flattening/) is turned off.
* On the DNS records table: you have filled in the CNAME record fields correctly, proxy status is set to **DNS only**, and **Flatten** is turned off.
* You have the correct NS configuration, and either:  
   * Make sure that the CNAME record is set as expected with the DNS provider that the NS record points to.  
   * Review your configuration for other DNS records that may be affected by the NS record. Once you are aware of any consequences or have made any necessary adjustments, remove the NS record so that the CNAME is resolved to the target you configured on Cloudflare.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/troubleshooting/cname-domain-verification/","name":"Verify a domain with CNAME"}}]}
```

---

---
title: NS records already exist
description: Resolve conflicts with existing NS records.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# NS records already exist

As you try to create a new DNS record, Cloudflare displays the following error:

```

NS records with that host already exist. (Code:81056)


```

## Causes

When a child domain (`blog.example.com`) of your domain (`example.com`) has been set up as a separate [subdomain zone](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/), corresponding `NS` records must have been placed within the parent zone.

When you are managing DNS records for the parent zone (in this example, `example.com`), you cannot create IP address resolution records (`A`, `AAAA`, or `CNAME`) with a name that specifies the same subdomain that already exists as a separate subdomain zone.

| Type | Name | Content   | TTL  |
| ---- | ---- | --------- | ---- |
| A    | blog | 192.0.2.0 | Auto |

## Solution

Before creating such records, remove any `NS` records with the same name.

Important

This action might be reverting an existing subdomain setup and may incur in downtime. Refer to [Rollback subdomain setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/rollback/) for more guidance.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/troubleshooting/existing-ns-record/","name":"NS records already exist"}}]}
```

---

---
title: Exposed IP addresses
description: Understand and resolve warnings about DNS records that expose your origin server IP address.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Exposed IP addresses

When your DNS records are [proxied](https://developers.cloudflare.com/dns/proxy-status/), Cloudflare speeds up and protects your site.

A `dig` query against your proxied apex domain returns a Cloudflare IP address. This way, your origin server's IP address remains concealed from the public. Proxy benefits only apply to HTTP traffic.

When your server's IP address is exposed, your server is more vulnerable to direct attacks. It is still possible (but more difficult) for attackers to determine your origin server IP address when proxying traffic to Cloudflare.

---

## Dashboard warnings

The Cloudflare dashboard displays warnings when DNS records may expose your origin server's IP address. These warnings do not block or affect traffic to your site.

When your zone has DNS records that are not proxied, the **DNS Records** page displays the following banner:

`Proxying is required for most security and performance features. Set your DNS records to proxied by clicking "Edit" in the table below, to benefit from DDoS protection, security rules, caching, and more.`

Individual DNS records may also display warnings. The specific message depends on whether the record can be proxied.

---

## DNS records that should be proxied

Cloudflare recommends [proxying](https://developers.cloudflare.com/dns/proxy-status/) any record that handles HTTP traffic so that a `dig` query returns a Cloudflare IP address instead of your origin server IP address.

To take advantage of Cloudflare's performance and security benefits, proxy `A`, `AAAA`, and `CNAME` records.

---

## DNS records that should be DNS-only

Some DNS records need to remain DNS-only. For example, you may have to host multiple services (for example, a website and email) on the same physical server.

When a DNS-only record points to the same origin server as a proxied record, a `dig` query against that record reveals your origin server's IP address. This makes it easier for potential attackers to target your origin server directly.

To mitigate this risk:

* Analyze the impact of hosting multiple services on the same origin server in cases when you cannot avoid having DNS-only records.
* Proxy all records that share the same origin IP address as your apex domain and can be safely proxied through Cloudflare.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/troubleshooting/exposed-ip-address/","name":"Exposed IP addresses"}}]}
```

---

---
title: Records with the same name
description: Handle multiple DNS records with the same name.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Records with the same name

Occasionally, Cloudflare will not allow you to [create new DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) with the same value in the **Name** field.

This error can occur due to the special requirements of CNAME records[1](#user-content-fn-1).

## Causes

You will encounter this error if you try to do one of the following:

* Create a CNAME record with a **Name** matching the name of an existing A/AAAA[2](#user-content-fn-2) or CNAME record.
* Create an A/AAAA record with a **Name** matching the name of an existing CNAME record.

Cloudflare prevents you from creating this combination of records because if a CNAME record is provided for a hostname DNS servers expect only that CNAME record to provide DNS information for that hostname.

Adding additional records would send conflicting information to DNS servers. For a technical explanation of the mechanism behind this, refer to [RFC 1034 ↗](https://www.rfc-editor.org/rfc/rfc1034).

## Solution

Review your existing DNS records to find the matching value in the **Name** field. Then, decide whether you want to keep the current record or delete it and make a new one.

Note

CNAME records are the only IP resolution record with this type of limitation. You can have more than one A/AAAA record per hostname, which is a way some domains do [simple load balancing](https://developers.cloudflare.com/dns/manage-dns-records/how-to/round-robin-dns/) for incoming requests.

## Footnotes

1. [CNAME records ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-cname-record/) map a domain name to another (canonical) domain name. They can be used to resolve other record types present on the target domain name.  
[↩](#user-content-fnref-1)
2. [A and AAAA records ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-a-record/) map a domain name to one or multiple IPv4 or IPv6 address(es).  
[↩](#user-content-fnref-2)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/troubleshooting/records-with-same-name/","name":"Records with the same name"}}]}
```

---

---
title: Stale response for upstream DNS resolution
description: Fix stale DNS responses from upstream resolvers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Stale response for upstream DNS resolution

In one of the scenarios below, you notice that stale DNS responses are used. Depending on the scenario and other aspects of your configuration, this can cause wrong content or no content to be returned.

* A proxied CNAME record ([flattened by default](https://developers.cloudflare.com/dns/cname-flattening/)).
* A DNS-only CNAME record that has flattening turned on. This can happen either via the specific record configuration or as a consequence of the [zone settings](https://developers.cloudflare.com/dns/cname-flattening/set-up-cname-flattening/).
* A [Workers](https://developers.cloudflare.com/workers/) script making a subrequest to an external hostname[1](#user-content-fn-1).

## Cause

In the event that an upstream DNS server takes too long to respond, or the upstream returns a SERVFAIL, Cloudflare will use the expired DNS response from the cache and then attempt to update that cache asynchronously.

## Solutions

* If possible, temporarily replace the proxied CNAME with a proxied A record. This may not always be possible, especially if the upstream target is a load balancer or if it returns dynamic responses.
* Report the issues to the zone owner or DNS provider for the upstream target that is unresponsive.
* You can also raise the issue through the DNS Operations Analysis and Research Center (DNS OARC). Consider its [chat platform ↗](https://www.dns-oarc.net/oarc/services/chat) or [email lists ↗](https://www.dns-oarc.net/oarc/lists).

## Footnotes

1. A hostname that is not using Cloudflare as its [authoritative DNS provider](https://developers.cloudflare.com/dns/concepts/#authoritative-dns). [↩](#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":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/troubleshooting/stale-response/","name":"Stale response for upstream DNS resolution"}}]}
```

---

---
title: Unexpected DNS records
description: Identify and remove unexpected DNS records.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Unexpected DNS records

## Additional records after import

You find several unexpected DNS records after adding your domain to Cloudflare.

### Cause

A wildcard (`*`) record at your previous authoritative DNS provider may have been imported into Cloudflare in a way that creates additional records.

### Solution

To solve this issue, you can do one of the following:

* [Delete records in bulk](https://developers.cloudflare.com/dns/manage-dns-records/how-to/batch-record-changes/#delete-records-in-bulk).
* Remove and re-add your domain:  
   1. [Remove your domain](https://developers.cloudflare.com/fundamentals/manage-domains/remove-domain/) from Cloudflare.  
   2. Delete the wildcard record from your authoritative DNS.  
   3. [Re-add](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) the domain.

---

## acme\_challenge TXT records

You might notice TXT records like `_acme-challenge.<hostname>` are returned by your domain but cannot be found on the Cloudflare dashboard.

### Cause

These records are automatically created to allow Cloudflare edge certificates ([universal](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/), [advanced](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/), and [backup](https://developers.cloudflare.com/ssl/edge-certificates/backup-certificates/)) to be provisioned. `_acme-challenge` records are required by certificate authorities (CAs) so that they can verify your domain ownership before issuing the SSL/TLS certificate. For details, refer to [Domain control validation (DCV)](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/).

### Solution

As these records are tied to the certificates, they cannot be deleted via the Cloudflare dashboard.

If you need more `_acme-challenge.<hostname>` TXT records in order to provision certificates on your side, you can [manually add them](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) under [DNS records ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records).

If you want to remove these records:

* [Disable Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/disable-universal-ssl/) to remove the records related to universal and backup certificates.
* [Delete advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/#delete-a-certificate) to remove the records related to advanced certificates.

---

## \_dc-mx and dc-##### subdomains

You notice a `_dc-mx` or `dc-#####` subdomain that you did not create (for example, `_dc-mx.a1b2c3d4e5f6.example.com`). This response does not appear in your Cloudflare DNS records table, but will appear in `dig` responses.

### Cause

When your `MX` or `SRV` record resolves to a domain configured to [proxy](https://developers.cloudflare.com/dns/proxy-status/) through Cloudflare, Cloudflare dynamically inserts a record into DNS responses that resolves to the origin IP address. This record is added at query time to ensure that mail or service traffic bypasses the Cloudflare proxy and reaches your server directly.

The prefix of the auto-generated record depends on the record type that triggered it:

* **MX records:** Cloudflare inserts a record with the `_dc-mx` prefix (for example, `_dc-mx.a1b2c3d4e5f6.example.com`).
* **SRV records:** Cloudflare inserts a record with the `dc-` prefix (for example, `dc-a1b2c3d4e5f6.example.com`).

#### How \_dc-mx records work

Before using Cloudflare, suppose your DNS records for mail are as follows:

`example.com MX example.com`

`example.com A 192.0.2.1`

After using Cloudflare and proxying the `A` record, Cloudflare provides DNS responses with a [Cloudflare IP address](https://developers.cloudflare.com/fundamentals/concepts/cloudflare-ip-addresses/) (`203.0.113.1` in the example below):

`example.com MX example.com`

`example.com A 203.0.113.1`

Since proxying mail traffic through Cloudflare would break your mail services, Cloudflare detects this situation and dynamically inserts a `_dc-mx` record into DNS responses:

`example.com MX _dc-mx.a1b2c3d4e5f6.example.com`

`_dc-mx.a1b2c3d4e5f6.example.com A 192.0.2.1`

`example.com A 203.0.113.1`

You can verify this behavior by querying your domain's MX records (replace `example.com` with your domain):

Terminal window

```

dig example.com mx +short


```

```

100 _dc-mx.a1b2c3d4e5f6.example.com.


```

The `_dc-mx` record resolves directly to your origin IP:

Terminal window

```

dig _dc-mx.a1b2c3d4e5f6.example.com a +short


```

```

192.0.2.1


```

### Solution

These records are safe — they ensure your mail traffic reaches your server correctly.

If you want to avoid a `_dc-mx` or `dc-#####` response, you must address the underlying proxy conflict:

* If no mail is received for the domain, delete the `MX` record.
* If mail is received for the domain, update the `MX` record to resolve to a separate `A` record for a mail subdomain that is not proxied by Cloudflare:  
`example.com MX mail.example.com`  
`mail.example.com A 192.0.2.1`  
`example.com A 203.0.113.1`

Warning

If your mail server resides on the same IP as your web server, your MX record will expose your origin IP address, since it is not hidden behind the Cloudflare proxy.

---

## Incorrect results for DNS queries

You notice DNS queries returning incorrect results even after you waited for the [TTL](https://developers.cloudflare.com/dns/manage-dns-records/reference/ttl/) to expire.

### Cause

Third-party tools can sometimes fail to return correct DNS results if a recursive DNS cache fails to refresh.

### Solution

In this circumstance, purge your public DNS cache via these methods:

* [Purge your DNS cache at OpenDNS ↗](http://www.opendns.com/support/cache/)
* [Purge your DNS cache at Google ↗](https://developers.google.com/speed/public-dns/cache)
* [Purge your DNS cache locally ↗](https://docs.cpanel.net/knowledge-base/dns/how-to-clear-your-dns-cache/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/manage-dns-records/","name":"DNS records"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/manage-dns-records/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/manage-dns-records/troubleshooting/unexpected-dns-records/","name":"Unexpected DNS records"}}]}
```

---

---
title: Proxy status
description: Control whether Cloudflare proxies traffic for DNS records.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Proxy status

While your [DNS records](https://developers.cloudflare.com/dns/manage-dns-records/) contain information about your domain, the proxy status controls whether HTTP/HTTPS traffic for that record routes through Cloudflare's network or goes directly to your origin server.

When a record is **Proxied**, Cloudflare sits between your visitors and your server — optimizing, caching, and protecting traffic along the way. When a record is **DNS-only**, Cloudflare responds with your server's actual IP address and does not route HTTP/HTTPS traffic through its network.

Only [records used for IP address resolution](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#ip-address-resolution) — A, AAAA, and CNAME records — can be proxied. Other record types (such as MX or TXT) are always DNS-only.

Cloudflare recommends proxying all A, AAAA, and CNAME records that serve web traffic. Records used for other purposes, such as [CNAME records that prove your domain ownership](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/cname-domain-verification/), should not be proxied.

Note

Proxying is on by default when you onboard a domain via the dashboard.

### Benefits

When you set a DNS record to **Proxied** — shown as an orange cloud icon in the dashboard, also known as "orange-clouded" — Cloudflare can:

* Protect your origin server (the server hosting your website or application) from [DDoS attacks ↗](https://www.cloudflare.com/learning/ddos/what-is-a-ddos-attack/).
* [Optimize, cache, and protect](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) all requests to your application.
* Apply your Cloudflare product configurations (such as [WAF](https://developers.cloudflare.com/waf/) rules, [caching](https://developers.cloudflare.com/cache/), and [redirect rules](https://developers.cloudflare.com/rules/url-forwarding/)) to incoming traffic.

Warning

When you [add a domain](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) to Cloudflare, Cloudflare protection will be in a [pending state](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/) until we can verify ownership. This could take up to 24 hours to complete. Refer to [Limitations](https://developers.cloudflare.com/dns/proxy-status/limitations/#pending-domains) for further guidance.

### Example

DNS management for **example.com**:

| Type | Name | Content   | Proxy status | TTL  |
| ---- | ---- | --------- | ------------ | ---- |
| A    | blog | 192.0.2.1 | Proxied      | Auto |
| A    | shop | 192.0.2.2 | DNS only     | Auto |

In the example DNS table above, there are two DNS records. The record with the name `blog` has proxy on, while the record named `shop` has the proxy off (that is, **DNS only**).

This means that:

* A DNS query to the proxied record `blog.example.com` will be answered with Cloudflare [anycast IP addresses](https://developers.cloudflare.com/fundamentals/concepts/cloudflare-ip-addresses/) — shared IP addresses used to route traffic through a nearby data center — instead of `192.0.2.1`. This ensures that HTTP/HTTPS requests for this name will be sent to Cloudflare's network and can be proxied, which allows the [benefits listed above](#benefits).
* A DNS query to the DNS-only record `shop.example.com` will be answered with the actual origin IP address, `192.0.2.2`. This exposes your origin IP address to anyone who queries the record, which removes a layer of protection against targeted attacks. Cloudflare also cannot provide HTTP/HTTPS analytics on those requests (only DNS analytics).

For further context, refer to [How Cloudflare works](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/).

---

## Proxied records

The sections below describe specific behaviors and expected outcomes when you have DNS records set to proxied. There may also be some [limitations](https://developers.cloudflare.com/dns/proxy-status/limitations/) in specific scenarios.

### Predefined time to live

By default, all proxied records have a time to live (TTL) of **Auto**, which is set to 300 seconds. This value cannot be edited.

This short TTL ensures that if Cloudflare changes the [anycast IP address](https://developers.cloudflare.com/fundamentals/concepts/cloudflare-ip-addresses/) assigned to your record, the change takes effect quickly. Recursive resolvers — the DNS servers that look up records on behalf of end users — will not cache the old address for longer than 300 seconds (five minutes).

Note

It may take longer than five minutes for you to actually experience record changes, as your local DNS cache may take longer to update. Also, Cloudflare reserves the right to change the TTL value at any time, although it is very rare and only done when necessary.

### Mix proxied and unproxied

If you have multiple A or AAAA records on the same name and at least one of them is proxied, Cloudflare will treat all A or AAAA records on this name as being proxied.

Example

DNS management for **example.com**:

| Type | Name | Content   | Proxy status | TTL  |
| ---- | ---- | --------- | ------------ | ---- |
| A    | blog | 192.0.2.1 | Proxied      | Auto |
| A    | blog | 192.0.2.5 | DNS only     | Auto |

In this example, all traffic intended for `blog.example.com` will be treated as if both records were **Proxied**.

Cloudflare will also proxy a request if a hostname on a CNAME chain — where one CNAME record points to another — is proxied.

Example

Consider that the same Cloudflare account has two different zones, `example.com` and `example.net`.

DNS management for **example.com**:

| Type  | Name        | Content            | Proxy status | TTL  |
| ----- | ----------- | ------------------ | ------------ | ---- |
| CNAME | example.com | origin.example.net | DNS only     | Auto |

DNS management for **example.net**:

| Type  | Name               | Content  | Proxy status | TTL  |
| ----- | ------------------ | -------- | ------------ | ---- |
| CNAME | origin.example.net | <origin> | Proxied      | Auto |

In this example, all traffic intended for `example.com` will be treated as **Proxied**.

Note

CNAME to a different Cloudflare account is prohibited and will result in a [Error 1014 (CNAME Cross-User Banned)](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-1xxx-errors/error-1014/)

### CNAME records

With [CNAME flattening](https://developers.cloudflare.com/dns/cname-flattening/), Cloudflare follows the CNAME chain to find the final IP address, helping DNS queries resolve faster. Proxied [CNAME records](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#cname) are flattened by default, as they return Cloudflare anycast IPs.

In some cases, Cloudflare will show a warning message or [prevent](https://developers.cloudflare.com/dns/proxy-status/limitations/#proxy-eligibility) you from proxying a CNAME record. This happens to avoid misconfigurations and is generally related to other CDN providers or to specific records used for [DKIM ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/) (email authentication) validation.

Note

Specific CNAME record values with traffic proxied through Cloudflare will enable O2O routing for the Shopify SaaS provider. Refer to the [Shopify provider guide](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/shopify/) for more information.

### Protocol optimization

For proxied records, if your domain has [HTTP/2 or HTTP/3 enabled](https://developers.cloudflare.com/speed/optimization/protocol/) and is also using [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/), Cloudflare automatically generates [HTTPS Service (HTTPS) records](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#svcb-and-https) on the fly. These DNS records provide clients with information about how to connect to your server upfront, without the need for an initial plaintext HTTP connection to discover supported protocols.

Note

Both HTTP/2 and HTTP/3 configurations also require that you have an SSL/TLS certificate served by Cloudflare. This means that disabling [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/), for example, could impact this behavior.

### Request and response size limits

Cloudflare enforces size limits on proxied requests. These limits vary by plan and cannot be bypassed while traffic is proxied. For the full list of connection and request limits, refer to [Connection limits](https://developers.cloudflare.com/fundamentals/reference/connection-limits/).

### Connection timeouts

Cloudflare enforces a default [Proxy Read Timeout](https://developers.cloudflare.com/fundamentals/reference/connection-limits/) between Cloudflare and your origin server. If your origin does not send an HTTP response within the defined time limit, Cloudflare returns a [524 error](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-524/). Enterprise customers can [increase the timeout value](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#proxy-read-timeout-enterprise-only).

---

## DNS-only records

When an A, AAAA, or CNAME record is **DNS-only** — shown as a gray cloud icon in the dashboard, also known as "gray-clouded" — DNS queries for these will resolve to the record's actual origin IP address, as described in the [example](#example).

**DNS-only** is only recommended for records that do not serve web traffic, such as records used for email routing or third-party domain verification. For records that serve web traffic, **DNS-only** means your origin IP addresses are visible to anyone who queries the record, potentially exposing your server to bad actors and [DDoS attacks ↗](https://www.cloudflare.com/learning/ddos/what-is-a-ddos-attack/). Cloudflare also cannot [optimize, cache, and protect](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/) those requests or provide HTTP/HTTPS analytics on them.

Note

If you have multiple `A/AAAA` records on the same name and at least one of them is proxied, Cloudflare will treat all `A/AAAA` records on this name as being proxied.

### When to use DNS-only

Certain DNS records should be DNS-only because the services they support are not compatible with Cloudflare's HTTP proxy. Common examples include email records, domain verification records, SaaS-hosted websites, and non-HTTP services.

For a detailed list of scenarios, refer to [Use cases](https://developers.cloudflare.com/dns/proxy-status/use-cases/). For hard constraints on proxying, refer to [Proxying limitations](https://developers.cloudflare.com/dns/proxy-status/limitations/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/proxy-status/","name":"Proxy status"}}]}
```

---

---
title: Enforce DNS-only
description: Bypass Cloudflare's reverse proxy for all zones at once.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Enforce DNS-only

The enforce DNS-only setting is an account-level break-glass mechanism that allows you to bypass Cloudflare's reverse proxy for all zones in your account in a single action. When enabled, Cloudflare responds to DNS queries with the underlying record content — origin IP addresses for proxied `A` and `AAAA` records, and CNAME targets for proxied `CNAME` records — instead of Cloudflare's anycast IP addresses, effectively setting all [proxied DNS records](https://developers.cloudflare.com/dns/proxy-status/) to DNS-only without modifying the records themselves.

This setting is intended for emergency situations only, such as during an outage when you need to quickly route traffic directly to your origins.

Warning

Enabling this setting exposes your origin IP addresses and removes all Cloudflare protections — including DDoS mitigation, WAF, caching, and all other proxy-based features — for every zone in your account. Use with extreme caution and only after proper [preparation](#preparation).

## Key characteristics

* Account-level: Affects all zones in the account simultaneously.
* Non-destructive: Does not modify your DNS records. Disabling the setting restores normal proxy behavior.
* API-only: Available through the API only, not in the Cloudflare dashboard.

Auto TTL for proxied records

Due to DNS caching by recursive resolvers, the transitions from proxied to DNS-only and back may not be instantaneous. Since all proxied records have a TTL of **Auto**, this value (five minutes by default) determines how long resolvers may continue to serve Cloudflare's anycast IPs or your origin IP addresses.

## Zone types

Enforce DNS-only works across all zone setup types:

* [Full setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/): Proxied records in the zone are generally affected, considering a few [exceptions](https://developers.cloudflare.com/dns/proxy-status/enforce-dns-only/#excluded).
* [Partial (CNAME) setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/): Proxied records in the zone are generally affected, considering a few [exceptions](https://developers.cloudflare.com/dns/proxy-status/enforce-dns-only/#excluded).
* [Secondary zones](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/): If Secondary DNS Overrides is enabled and you have manually set a record's proxy status to proxied, that record will be affected. This also applies to any other `A` or `AAAA` records on the same name. Refer to [Secondary DNS Overrides](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/proxy-traffic/) for details.  
Zone transfers interaction  
While enforce DNS-only is active, zone transfers from the primary (including content or TTL changes) do not change the proxy status of affected records. When you [disable enforce DNS-only](#disable-enforce-dns-only), the records return to proxied.

## Preparation

Before relying on enforce DNS-only as part of your incident response plan, you should:

* Verify origin server capacity: Without Cloudflare proxying, your origin servers handle all traffic directly, including traffic that Cloudflare would normally cache or filter. Ensure your infrastructure can sustain this load.
* Review exposed record content: When enforce DNS-only is active, all origin IPs configured in proxied `A` and `AAAA` records, as well as the targets of proxied `CNAME` records, become publicly visible through DNS queries. If your origins rely on IP obscurity for security, plan accordingly.
* Test in advance: Use the API in a staging or test account to confirm that you understand the behavior before you need it in an emergency.

Verify SSL certificates

If your origins serve HTTPS traffic, ensure they have publicly trusted SSL certificates installed for the relevant hostnames. Cloudflare [Origin CA certificates](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/) are only trusted by Cloudflare and will cause certificate errors for direct client connections.

## Enable enforce DNS-only

Use the [Update DNS Settings](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/account/methods/edit/) endpoint to enable enforce DNS-only for your account:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Account DNS Settings Write`

Update DNS Settings

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/dns_settings" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "enforce_dns_only": true

  }'


```

Once enabled, Cloudflare responds to DNS queries for all proxied records with the underlying record content — your configured origin IP addresses for `A` and `AAAA` records, and the configured CNAME target for `CNAME` records — instead of Cloudflare's anycast IPs.

## Disable enforce DNS-only

To restore normal proxy behavior, set `enforce_dns_only` to `false`:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Account DNS Settings Write`

Update DNS Settings

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/dns_settings" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "enforce_dns_only": false

  }'


```

After you disable the setting, Cloudflare resumes responding to DNS queries with anycast IP addresses for proxied records and all proxy-based features are restored.

## Other Cloudflare products

Refer to the sections below in case you use other Cloudflare products that rely on DNS records.

### Included

Enforce DNS-only affects the following records:

* [Load Balancing](https://developers.cloudflare.com/load-balancing/): proxied LB records visible on the DNS records table but managed through the [Load Balancing configurations](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/).
* Proxied DNS records that match a [Worker route](https://developers.cloudflare.com/workers/configuration/routing/routes/).
* [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) fallback origin: The proxied DNS record you designate as the [fallback origin](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#1-create-fallback-origin) for custom hostnames.

### Excluded

Enforce DNS-only does not affect the following records:

* [R2](https://developers.cloudflare.com/r2/) custom domains: Read-only proxied records added to the DNS records table when you set up [R2 custom domains](https://developers.cloudflare.com/r2/buckets/public-buckets/#connect-a-bucket-to-a-custom-domain).
* [Spectrum](https://developers.cloudflare.com/spectrum/) applications: DNS records managed by the Spectrum application.
* [Tunnel](https://developers.cloudflare.com/tunnel/): CNAME records pointing to a tunnel subdomain. Refer to [Tunnel routing](https://developers.cloudflare.com/tunnel/routing/#create-a-dns-record) or [Cloudflare One](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/routing-to-tunnel/dns/) for details.
* [Web3 gateways](https://developers.cloudflare.com/web3/): Read-only proxied records managed by the [Web3 gateway configuration](https://developers.cloudflare.com/web3/reference/gateway-dns-records/).
* [Workers](https://developers.cloudflare.com/workers/) custom domains: Read-only proxied records added to the DNS records table when you set up Workers [custom domains](https://developers.cloudflare.com/workers/configuration/routing/custom-domains/).  
Custom domain or route match  
Proxied records that match a Worker [route](https://developers.cloudflare.com/workers/configuration/routing/routes/) are regular DNS records and will be [affected](#included) by the enforce DNS-only setting.

## Check current status

Use the [Show DNS Settings](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/account/methods/get/) endpoint to verify the current value:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Account DNS Settings Write`
* `Account DNS Settings Read`

Show DNS Settings

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/dns_settings" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

## Related resources

* [Proxy status](https://developers.cloudflare.com/dns/proxy-status/) \- Understand how proxied and DNS-only records behave.
* [Batch record changes](https://developers.cloudflare.com/dns/manage-dns-records/how-to/batch-record-changes/#edit-proxy-status-in-bulk) \- Change proxy status for multiple records in bulk within a single zone.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/proxy-status/","name":"Proxy status"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/proxy-status/enforce-dns-only/","name":"Enforce DNS-only"}}]}
```

---

---
title: Proxying limitations
description: Limitations when proxying DNS records through Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Proxying limitations

This page describes expected limitations when proxying DNS records. For further information about proxying, refer to [How Cloudflare DNS works](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/).

For guidance on when to proxy records and when to use DNS only, refer to [Use cases](https://developers.cloudflare.com/dns/proxy-status/use-cases/).

## Proxy eligibility

Only A, AAAA, and CNAME records that serve HTTP or HTTPS traffic can be proxied. Other DNS record types cannot be proxied.

If you encounter a [CNAME record](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#cname) that you cannot proxy — usually associated with another CDN provider — a proxied version of that record will cause connectivity errors. Cloudflare is purposely preventing that record from being proxied to protect you from a misconfiguration.

Non-proxiable targets

* Exact match:  
   * `dkim2.mcsv.net` ([Mailchimp documentation ↗](https://mailchimp.com/help/set-up-email-domain-authentication/))  
   * `dkim3.mcsv.net` ([Mailchimp documentation ↗](https://mailchimp.com/help/set-up-email-domain-authentication/))  
   * `zmverify.zoho.com` ([Zoho documentation ↗](https://www.zoho.com/mail/help/adminconsole/domain-verification.html))  
   * `dkim.infusionmail.com` ([Keap documentation ↗](https://help.keap.com/help/dmarc))
* Exact match or subdomain of:  
   * `dkim.amazonses.com` ([Amazon SES documentation ↗](https://docs.aws.amazon.com/ses/latest/dg/creating-identities.html#just-verify-domain-proc))
* Subdomain of:  
   * `onmicrosoft.com` ([Microsoft documentation ↗](https://learn.microsoft.com/defender-office-365/email-authentication-dkim-configure))  
   * `dkim.intercom.io` ([Intercom documentation ↗](https://www.intercom.com/help/articles/9744849-connect-your-email-support-channel))  
   * `acm-validations.aws` ([AWS certificate manager documentation ↗](https://docs.aws.amazon.com/acm/latest/userguide/dns-validation.html))

### Pre-signed DNSSEC

If you use Cloudflare as your [secondary DNS provider](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) and leverage [Secondary DNS Overrides](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/proxy-traffic/) to set records to proxied, note that opting for [Pre-signed DNSSEC](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/dnssec-for-secondary/) will cause Cloudflare to treat your records as DNS-only.

## Ports and protocols

To proxy HTTP/HTTPS traffic on [non-standard ports](https://developers.cloudflare.com/fundamentals/reference/network-ports/) or to proxy a TCP or UDP based application, use [Cloudflare Spectrum](https://developers.cloudflare.com/spectrum/).

## Pending domains

When you [add a domain](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) to Cloudflare, Cloudflare protection will be in a [pending state](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/) until we can verify ownership. This could take up to 24 hours to complete.

This means that DNS records — even those set to [proxy traffic through Cloudflare](#proxy-eligibility) — will be [DNS-only](https://developers.cloudflare.com/dns/proxy-status/#dns-only-records) until your zone has been activated and any requests to your DNS records will return your origin server's IP address.

If this warning is still present after 24 hours, refer to [Troubleshooting](https://developers.cloudflare.com/dns/troubleshooting/).

For enhanced security, we recommend rolling your origin IP addresses at your hosting provider after your zone has been activated. This action prevents your origin IPs from being leaked during onboarding.

## Windows authentication

Because Microsoft Integrated Windows Authentication, NTLM, and Kerberos violate HTTP/1.1 specifications, they are not compatible with proxied DNS records. NTLM authenticates at the TCP connection level (Layer 4), and Cloudflare does not guarantee that consecutive requests from the same client reuse the same TCP connection to the origin. This can cause repeated authentication prompts or authentication loops.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/proxy-status/","name":"Proxy status"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/proxy-status/limitations/","name":"Proxying limitations"}}]}
```

---

---
title: Use cases
description: Common scenarios for proxied and DNS-only records.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Use cases

This page lists common scenarios where DNS records should be proxied or set to DNS only, and describes aspects to keep in mind depending on your configuration. For background on how proxy status works, refer to [Proxy status](https://developers.cloudflare.com/dns/proxy-status/).

## Proxied records

You should proxy all A, AAAA, and CNAME records that serve HTTP or HTTPS web traffic. This includes records for:

* Your website or web application (for example, `example.com`, `www.example.com`)
* Subdomains that serve web content (for example, `blog.example.com`, `app.example.com`)
* API endpoints that accept HTTP/HTTPS requests and do not require origin IP validation

Proxied records benefit from [DDoS protection ↗](https://www.cloudflare.com/learning/ddos/what-is-a-ddos-attack/), [caching](https://developers.cloudflare.com/cache/), [WAF](https://developers.cloudflare.com/waf/), and other Cloudflare security and performance features.

When traffic is proxied through Cloudflare, the following behaviors apply. You may need to adjust your origin configuration, depending on your use case.

### Source IP changes

Your origin server sees Cloudflare IP addresses as the source of all requests instead of the end-user's IP address. Applications that rely on the source IP for authentication, rate limiting, or geolocation will not function as expected without additional configuration.

Cloudflare includes the original visitor IP address in the [CF-Connecting-IP](https://developers.cloudflare.com/fundamentals/reference/http-headers/) and `X-Forwarded-For` request headers. Configure your origin server to read the visitor IP from these headers. For more information, refer to [Restoring original visitor IPs](https://developers.cloudflare.com/support/troubleshooting/restoring-visitor-ips/restoring-original-visitor-ips/).

### Client certificate (mTLS) validation

When a record is proxied, TLS terminates at Cloudflare's global network. Cloudflare establishes a separate TLS connection to your origin server. This means the origin never receives the end-user's client certificate during the TLS handshake. You can achieve mTLS through the following:

* [Client certificates (mTLS)](https://developers.cloudflare.com/ssl/client-certificates/): validate client certificates between your end-users and Cloudflare.
* [Authenticated Origin Pulls](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/): Verify that traffic reaching your origin comes from Cloudflare.
* [Forward a client certificate](https://developers.cloudflare.com/ssl/client-certificates/forward-a-client-certificate/): Forward client certificate details to your origin via HTTP headers.

### Header modifications

Cloudflare adds and modifies HTTP request headers when proxying traffic, including headers for [visitor IP identification](https://developers.cloudflare.com/fundamentals/reference/http-headers/), diagnostics, and connection management. Applications that expect a fixed number of headers or parse headers by position instead of by name may experience errors.

For a full list of headers that Cloudflare adds or modifies, refer to [HTTP request headers](https://developers.cloudflare.com/fundamentals/reference/http-headers/).

## DNS only

The following records should be set to DNS-only because the services they support are not compatible with Cloudflare's HTTP proxy. Proxying these records causes the associated service to break.

### Email

MX records cannot be proxied. If an A or AAAA record is used exclusively for email (for example, `mail.example.com`), it should also be set to DNS-only.

Cloudflare does not proxy SMTP traffic on port `25` by default. Proxying a record that handles email traffic causes mail servers to connect to Cloudflare's IP addresses instead of your mail server. This prevents email delivery.

Use a dedicated hostname for email that is separate from your proxied web traffic hostname. If your MX record points to the same hostname as your website, Cloudflare [dynamically prepends](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/unexpected-dns-records/#%5Fdc-mx-and-dc--subdomains) `_dc-mx` to the hostname in the response for the MX record. This ensures that mail or service traffic bypasses the Cloudflare proxy and reaches your server directly.

Note

You can proxy SMTP traffic if you have [Cloudflare Spectrum](https://developers.cloudflare.com/spectrum/) configured for [SMTP](https://developers.cloudflare.com/spectrum/reference/configuration-options/#smtp).

### Domain verification

Third-party services often require CNAME or TXT records to verify domain ownership. Proxying a verification CNAME record returns Cloudflare IP addresses instead of the expected verification target. The third-party service cannot match the response and verification fails.

Common services that require DNS-only verification records:

* Google Workspace
* AWS Certificate Manager (`acm-validations.aws`)
* Squarespace (`verify.squarespace.com`)
* Amazon Amplify

Set domain verification records to **DNS Only** until verification completes. Some services require the record to be DNS-only permanently.

### SaaS-hosted websites

If your site is hosted on a SaaS platform (for example, [Wix](https://developers.cloudflare.com/dns/manage-dns-records/reference/vendor-specific-records/#wix), Squarespace, Webflow), the platform serves your site from its own infrastructure. Proxying the DNS record pointing to a SaaS platform causes one or more of the following issues:

* **SSL errors**: Both Cloudflare and the SaaS platform attempt to terminate SSL, which causes certificate mismatches or handshake failures.
* **Redirect loops**: Both services try to redirect HTTP to HTTPS, which creates an infinite loop.
* **Broken pages or assets**: The platform rejects requests that do not come directly from the expected DNS resolution.

If your SaaS platform does not explicitly support Cloudflare's proxy, set the record to **DNS-only**. Refer to [vendor-specific DNS records](https://developers.cloudflare.com/dns/manage-dns-records/reference/vendor-specific-records/) for platform-specific guidance.

Note

Some SaaS platforms are integrated with Cloudflare through [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/). For example, Shopify uses [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/shopify/), which allows proxied records to work correctly.

### Non-HTTP services

Records used for FTP, SSH, RDP, game servers, or other non-HTTP protocols must be DNS-only. Cloudflare's proxy only handles HTTP and HTTPS traffic. Proxying these records routes the traffic to Cloudflare, which drops the non-HTTP connection.

To proxy non-HTTP protocols, use [Cloudflare Spectrum](https://developers.cloudflare.com/spectrum/).

### Other CDN or proxy providers

If a CNAME record points to another CDN or proxy provider (for example, AWS CloudFront, Akamai, Fastly), proxying it through Cloudflare can cause conflicts between the two proxies:

* **SSL negotiation failures**: Both proxies attempt to terminate TLS, which creates certificate chain errors.
* **Routing loops**: Each proxy forwards requests back to the other.
* **Connectivity errors**: The upstream CDN rejects requests from Cloudflare's IP addresses.

Cloudflare automatically [prevents proxying](https://developers.cloudflare.com/dns/proxy-status/limitations/#proxy-eligibility) for some known targets. For targets that are not automatically blocked, set the record to **DNS-only** if you experience connectivity issues.

### API and webhook origin validation

Some third-party services validate the origin IP address of incoming API calls or webhook deliveries. When you proxy the DNS record for an endpoint that sends outbound requests or receives webhooks, the remote service sees Cloudflare's IP addresses instead of your server's IP address. This causes the validation to fail.

If a third-party service requires IP-based validation and does not accept [Cloudflare's IP ranges ↗](https://www.cloudflare.com/ips/), set the record for that service to **DNS-only**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/proxy-status/","name":"Proxy status"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/proxy-status/use-cases/","name":"Use cases"}}]}
```

---

---
title: DNSSEC
description: Protect your domain from DNS spoofing with DNSSEC.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNSSEC

DNS Security Extensions (DNSSEC) adds an extra layer of authentication to DNS, ensuring requests are not routed to a spoofed domain.

For additional background on DNSSEC, visit the [Cloudflare Learning Center ↗](https://www.cloudflare.com/learning/dns/dns-security/).

---

## Disable DNSSEC

If you are onboarding an existing domain to Cloudflare, make sure DNSSEC **is disabled** at your registrar (where you purchased your domain name). Otherwise, your domain will experience connectivity errors when you change your nameservers.

Provider-specific DNSSEC instructions

This is not an exhaustive list, but the following links may be helpful:

* [DNSimple ↗](https://support.dnsimple.com/articles/cloudflare-ds-record/)
* [Domaindiscount24 ↗](https://support.domaindiscount24.com/hc/articles/4409759478161)
* [DreamHost ↗](https://help.dreamhost.com/hc/en-us/articles/219539467)
* [Dynadot ↗](https://www.dynadot.com/help/question/set-DNSSEC)
* [Enom ↗](https://support.enom.com/support/solutions/articles/201000065386)
* [Gandi ↗](https://docs.gandi.net/en/domain%5Fnames/advanced%5Fusers/dnssec.html)
* [GoDaddy ↗](https://www.godaddy.com/help/add-a-ds-record-23865)
* [Hostinger ↗](https://www.hostinger.com/support/3667267-how-to-use-dnssec-records-at-hostinger/)
* [Hover ↗](https://support.hover.com/support/solutions/articles/201000064716)
* [Infomaniak ↗](https://faq.infomaniak.com/2187)
* [InMotion Hosting ↗](https://www.inmotionhosting.com/support/edu/cpanel/enable-dnssec-cloudflare/)
* [INWX ↗](https://kb.inwx.com/en-us/3-nameserver/131)
* [Joker.com ↗](https://joker.com/faq/books/jokercom-faq-en/page/dnssec)
* [Name.com ↗](https://www.name.com/support/articles/205439058-managing-dnssec)
* [Namecheap ↗](https://www.namecheap.com/support/knowledgebase/article.aspx/9722/2232/managing-dnssec-for-domains-pointed-to-custom-dns/)
* [NameISP ↗](https://support.nameisp.com/knowledgebase/dns)
* [Namesilo ↗](https://www.namesilo.com/support/v2/articles/domain-manager/ds-records)
* [OVH ↗](https://help.ovhcloud.com/csm/en-dns-secure-domain-dnssec?id=kb%5Farticle%5Fview&sysparm%5Farticle=KB0051637)
* [Squarespace ↗](https://support.squarespace.com/hc/articles/4404183898125-Nameservers-and-DNSSEC-for-Squarespace-managed-domains#toc-dnssec)
* [Registro.br ↗](https://registro.br/tecnologia/dnssec/?secao=tutoriais-dns)
* [Porkbun ↗](https://kb.porkbun.com/article/93-how-to-install-dnssec) (do not fill out **keyData**)
* [TransIP ↗](https://www.transip.eu/knowledgebase/150-secure-domains-custom-nameservers-dnssec/)

Why you have to disable DNSSEC

When your domain has [DNSSEC enabled ↗](https://www.cloudflare.com/learning/dns/dns-security/#what-is-dnssec), your DNS provider digitally signs all your DNS records. This action prevents anyone else from issuing false DNS records on your behalf and redirecting traffic intended for your domain.

However, having a single set of signed records also prevents Cloudflare from issuing new DNS records on your behalf (which is part of using Cloudflare for your authoritative nameservers). So if you change your nameservers without disabling DNSSEC, DNSSEC will prevent Cloudflare's DNS records from resolving properly.

Note

If your previous provider allows you to add DNSKEY records on the zone apex and use these records in responses to DNS queries, refer to this [migration tutorial](https://developers.cloudflare.com/dns/dnssec/dnssec-active-migration/) to learn how to migrate a zone with DNSSEC enabled.

---

## Enable DNSSEC

When you enable DNSSEC, Cloudflare signs your zone, publishes your public signing keys, and generates your **DS** record.

### 1\. Activate DNSSEC in Cloudflare

1. In the Cloudflare dashboard, go to the **DNS Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings)
2. For **DNSSEC**, click **Enable DNSSEC**.
3. In the dialog, you have access to several necessary values to help you create a **DS** record at your registrar. Once you close the dialog, you can access this information by clicking **DS record** on the **DNSSEC** card.

### 2\. Add DS record to your registrar

Add the **DS** record to your registrar. If Algorithm 13 - Cloudflare's preferred cipher choice - is not listed by your registrar, it may also be called _ECDSA Curve P-256 with SHA-256_.

Provider-specific DNSSEC instructions

This is not an exhaustive list, but the following links may be helpful:

* [DNSimple ↗](https://support.dnsimple.com/articles/cloudflare-ds-record/)
* [Domaindiscount24 ↗](https://support.domaindiscount24.com/hc/articles/4409759478161)
* [DreamHost ↗](https://help.dreamhost.com/hc/en-us/articles/219539467)
* [Dynadot ↗](https://www.dynadot.com/help/question/set-DNSSEC)
* [Enom ↗](https://support.enom.com/support/solutions/articles/201000065386)
* [Gandi ↗](https://docs.gandi.net/en/domain%5Fnames/advanced%5Fusers/dnssec.html)
* [GoDaddy ↗](https://www.godaddy.com/help/add-a-ds-record-23865)
* [Hostinger ↗](https://www.hostinger.com/support/3667267-how-to-use-dnssec-records-at-hostinger/)
* [Hover ↗](https://support.hover.com/support/solutions/articles/201000064716)
* [Infomaniak ↗](https://faq.infomaniak.com/2187)
* [InMotion Hosting ↗](https://www.inmotionhosting.com/support/edu/cpanel/enable-dnssec-cloudflare/)
* [INWX ↗](https://kb.inwx.com/en-us/3-nameserver/131)
* [Joker.com ↗](https://joker.com/faq/books/jokercom-faq-en/page/dnssec)
* [Name.com ↗](https://www.name.com/support/articles/205439058-managing-dnssec)
* [Namecheap ↗](https://www.namecheap.com/support/knowledgebase/article.aspx/9722/2232/managing-dnssec-for-domains-pointed-to-custom-dns/)
* [NameISP ↗](https://support.nameisp.com/knowledgebase/dns)
* [Namesilo ↗](https://www.namesilo.com/support/v2/articles/domain-manager/ds-records)
* [OVH ↗](https://help.ovhcloud.com/csm/en-dns-secure-domain-dnssec?id=kb%5Farticle%5Fview&sysparm%5Farticle=KB0051637)
* [Squarespace ↗](https://support.squarespace.com/hc/articles/4404183898125-Nameservers-and-DNSSEC-for-Squarespace-managed-domains#toc-dnssec)
* [Registro.br ↗](https://registro.br/tecnologia/dnssec/?secao=tutoriais-dns)
* [Porkbun ↗](https://kb.porkbun.com/article/93-how-to-install-dnssec) (do not fill out **keyData**)
* [TransIP ↗](https://www.transip.eu/knowledgebase/150-secure-domains-custom-nameservers-dnssec/)

Note:

Cloudflare automatically adds **DS** records for domains using Cloudflare Registrar or those using `.ch` and `.cz` top-level domains.

---

## Other DNSSEC setup options

If you are using Cloudflare as your Secondary DNS provider and want to configure DNSSEC on your secondary zone(s), you have [three options](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/dnssec-for-secondary/) depending on your setup.

If you want to set up DNSSEC on a subdomain zone, refer to [Subdomain DNSSEC](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/dnssec/).

---

## Limitations

If your registrar does not support DNSSEC with Cloudflare's preferred cipher choice (Algorithm 13), you have several options:

* Contact your registrar to ask for DNSSEC with modern encryption.
* Transfer your domain to a different registrar that supports DNSSEC with Algorithm 13
* File a [complaint with ICANN ↗](https://www.icann.org/compliance/complaint), citing your registrar's lack of compliance.

If your top-level domain does not support DNSSEC with Algorithm 13 (also known as _ECDSA Curve P-256 with SHA-256_), [contact that top-level domain ↗](https://www.iana.org/domains/root/db).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/dnssec/","name":"DNSSEC"}}]}
```

---

---
title: Migrate an existing zone with DNSSEC enabled
description: Follow this tutorial to migrate an existing DNS zone to Cloudflare without having to disable DNSSEC.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Migrate an existing zone with DNSSEC enabled

Follow this tutorial to migrate an existing DNS zone to Cloudflare without having to disable DNSSEC.

Warning

This procedure involves cross-importing the [zone signing keys (ZSKs) ↗](https://www.cloudflare.com/learning/dns/dns-records/dnskey-ds-records/) from one provider to the other. To learn more about this, consider this article [about multi-signer DNSSEC](https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/about/) or refer to [RFC 8901 ↗](https://www.rfc-editor.org/rfc/rfc8901.html).

This is an advanced procedure and assume some familiarity with [DNS concepts](https://developers.cloudflare.com/dns/concepts/), [API operations](https://developers.cloudflare.com/fundamentals/api/), and basic setup steps. Assumed knowledge that is not detailed in this tutorial can be referenced through the linked content in each of the steps.

## Requirement

The provider you are migrating from must allow you to add DNSKEY records on the zone apex and use these records in responses to DNS queries.

## 1\. Set up Cloudflare

1. [Add your zone to Cloudflare](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/).  
To add your zone using the API, refer to the [Create Zone endpoint](https://developers.cloudflare.com/api/resources/zones/methods/create/).
2. [Review the records found by the automatic scan](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) or [import your zone file](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/).  
To import the zone file using the API, refer to the [Import DNS Records endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/import/).
3. On the [**DNS Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings) page, select **Enable DNSSEC**. Or use the following [API request](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/edit/).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Edit DNSSEC Status

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dnssec" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "status": "active"

  }'


```

1. On the [**DNS Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings) page, enable **Multi-signer DNSSEC**. Or use the following [API request](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/edit/).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Edit DNSSEC Status

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dnssec" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "dnssec_multi_signer": true

  }'


```

## 2\. Cross-import ZSKs

1. Add the [ZSK ↗](https://www.cloudflare.com/learning/dns/dns-records/dnskey-ds-records/) of your previous provider to Cloudflare by creating a DNSKEY record on your zone.

You can do this [on the dashboard](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) or through the [Create DNS Record endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/), as in the following example.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Create DNS Record

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "type": "DNSKEY",

    "name": "<ZONE_NAME>",

    "data": {

        "flags": 256,

        "protocol": 3,

        "algorithm": 13,

        "public_key": "<PUBLIC_KEY>"

    },

    "ttl": 3600

  }'


```

1. Get Cloudflare's ZSK using either the API or a query from one of the assigned Cloudflare nameservers.

API example:

Terminal window

```

curl https://api.cloudflare.com/client/v4/zones/{zone_id}/dnssec/zsk \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>"


```

Command line query example:

Terminal window

```

dig <ZONE_NAME> dnskey @<CLOUDFLARE_NAMESERVER> +noall +answer | grep 256


```

1. Add Cloudflare's ZSK that you fetched in the last step to your previous provider.

Note

You can check if both providers are responding with both ZSKs by running one `dig` command for each, as in the following example. You can also use [Dig Web Interface ↗](https://www.digwebinterface.com/?type=DNSKEY).

Terminal window

```

dig <ZONE_NAME> dnskey @<PREVIOUS_PROVIDER_NAMESERVER> +noall +answer

dig <ZONE_NAME> dnskey @<CLOUDFLARE_NAMESERVER> +noall +answer


```

Both queries should return both ZSKs (identified with tag `256`).

Example

Terminal window

```

dig multisigner.info dnskey @dns1.p01.nsone.net. +noall +answer


```

```

multisigner.info.    3600    IN    DNSKEY    257 3 13 t+4D<bla_bla_bla>JBmA==

multisigner.info.    3600    IN    DNSKEY    256 3 13 pxEU<bla_bla_bla>0xOg==

multisigner.info.    3600    IN    DNSKEY    256 3 13 oJM<bla_bla_bla>XhSA==


```

Terminal window

```

dig multisigner.info dnskey @ashley.ns.cloudflare.com +noall +answer


```

```

multisigner.info.    3600    IN    DNSKEY    257 3 13 mdss<bla_bla_bla>eKGQ==

multisigner.info.    3600    IN    DNSKEY    256 3 13 oJM<bla_bla_bla>XhSA==

multisigner.info.    3600    IN    DNSKEY    256 3 13 pxEU<bla_bla_bla>0xOg==


```

## 3\. Set up registrar

1. Add Cloudflare DS record to your registrar. You can see your Cloudflare DS record on the [**DNS Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings) page, under **DS Record**.
2. Add Cloudflare assigned nameservers to your registrar. You can see your Cloudflare nameservers on the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page

At this point your zone is in a [multi-signer DNSSEC setup](https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/).

## 4\. Remove previous provider

1. Remove your previous provider's DS record from your registrar.
2. Remove your previous provider's nameservers from your registrar.
3. After waiting at least one and a half times the [TTL ↗](https://www.cloudflare.com/learning/cdn/glossary/time-to-live-ttl/) of your previous provider DS record, you can remove the DNSKEY record (containing your previous provider ZSK) that you added to your Cloudflare zone in [step 2](#2-cross-import-zsks).

Note

You can find out the TTL of your previous provider DS record by running a `dig` command, as in the following example, or by using this [Dig Web Interface link ↗](https://www.digwebinterface.com/?type=DS).

Terminal window

```

dig multisigner.info ds +noall +answer


```

```

multisigner.info. 3600 IN DS 2371 13 2 227B4C7FF3E1D49D59BAF39BDA54CA0839DE700DD9896076AA3E6AD7 19A0CF55

multisigner.info. 3600 IN DS 48553 13 2 893709B51A9C53D011A4054B15FC5454BEDF68E739BB3B3FA1E333DA 7B8DACFE


```

In this example, both DS records have a TTL of `3600` seconds. Cloudflare's DS record always has the key tag set to `2371`, so the second line of the response is the DS record of the other provider.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/dnssec/","name":"DNSSEC"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/dnssec/dnssec-active-migration/","name":"Migrate an existing zone with DNSSEC enabled"}}]}
```

---

---
title: DNSSEC states
description: Possible DNSSEC states and their meanings.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNSSEC states

This page describes different DNSSEC states and how they relate to the responses you get from the [DNSSEC details API endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/get/).

| State            | API response                                             | Description                                                                                                                                                                                                                  |
| ---------------- | -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Pending          | "status":"pending" "modified\_on":<TIME\_STAMP>          | DNSSEC has been enabled but the Cloudflare DS record has not been added at the registrar.                                                                                                                                    |
| Active           | "status":"active" "modified\_on":<TIME\_STAMP>           | DNSSEC has been enabled and the Cloudflare DS record is present at the registrar.                                                                                                                                            |
| Pending-disabled | "status":"pending-disabled" "modified\_on":<TIME\_STAMP> | DNSSEC has been disabled but the Cloudflare DS record is still added at the registrar.                                                                                                                                       |
| Disabled         | "status":"disabled" "modified\_on":<TIME\_STAMP>         | DNSSEC has been disabled and the Cloudflare DS record has been removed from the registrar.                                                                                                                                   |
| Deleted          | "status":"disabled" "modified\_on": null                 | DNSSEC has never been enabled for the zone or DNSSEC has been disabled and then deleted using the [Delete DNSSEC records endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/delete/). |

Warning

Once you have enabled DNSSEC on a zone for the first time, you cannot transition directly from an `active` state to a `deleted` state. You can only [delete DNSSEC records](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/delete/) once your zone DNSSEC is in a `disabled` state. Cloudflare prevents you from deleting DNSSEC records before removing the DS record from the registrar to avoid DNS resolution issues.

In both `pending` and `active` states, Cloudflare signs the zone and responds with RRSIG, NSEC, DNSKEY, CDS, and CDNSKEY record types.

In `pending-disabled` and `disabled` states, Cloudflare still signs the zone and serves RRSIG, NSEC, and DNSKEY record types, but the CDS and CDNSKEY records are set to zero ([RFC 8078 ↗](https://www.rfc-editor.org/rfc/rfc8078.html#section-4)), signaling to the registrar that DNSSEC should be disabled.

In `deleted` state, Cloudflare does **not** sign the zone and does **not** respond with RRSIG, NSEC, DNSKEY, CDS, and CDNSKEY record types.

Refer to [How DNSSEC works ↗](https://www.cloudflare.com/dns/dnssec/how-dnssec-works/) to learn more about the authentication process and records involved.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/dnssec/","name":"DNSSEC"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/dnssec/dnssec-states/","name":"DNSSEC states"}}]}
```

---

---
title: NSEC3 support
description: Learn how to enable NSEC3 support with Cloudflare to meet compliance requirements.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# NSEC3 support

As explained in [our blog ↗](https://blog.cloudflare.com/black-lies/), Cloudflare's implementation of negative answers with NSEC is protected against zone walking[1](#user-content-fn-1). This implementation, also referred to as Compact Denial of Existence ([RFC 9824 ↗](https://www.rfc-editor.org/rfc/rfc9824.html)), removes the need for NSEC3 and is significantly more efficient.

However, if you must use NSEC3 for compliance reasons, you can enable it as explained below.

## Enable NSEC3

Use the [Edit DNSSEC Status endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/edit/), setting `status` to `active` and `dnssec_use_nsec3` to `true`. You should replace the values started by `$` with your zone ID and authentication credentials. To learn more about using the Cloudflare API, refer to [Fundamentals](https://developers.cloudflare.com/fundamentals/api/get-started/).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Edit DNSSEC Status

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dnssec" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "dnssec_use_nsec3": true,

    "status": "active"

  }'


```

### Pre-signed DNSSEC

If you use Cloudflare as a secondary DNS provider with [pre-signed DNSSEC](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/dnssec-for-secondary/), setting `dnssec_use_nsec3` to `true` means that Cloudflare will use NSEC3 records as transferred in from your primary DNS provider.

Otherwise, NSEC3 records will be generated and signed at request time.

## Verify NSEC3 is in use

To validate that NSEC3 is being used, consider the following scenarios:

### Non-existent zone name

A command like the following would trigger a signed negative response using NSEC3 for proof of non-existence. Look for NSEC3 records under the `Authority Section` of the response.

Terminal window

```

dig +dnssec doesnotexist.example.com


```

### Non-existent record type at an existing name

If the name `www` exists but the type TXT does not, the example below would trigger a signed NODATA response using NSEC3\. Look for NSEC3 records under the `Authority Section` of the response.

Terminal window

```

dig +dnssec www.example.com TXT


```

## Availability

NSEC3 is only available for zones on the Enterprise plan.

## Footnotes

1. A method where an attacker exploits NSEC negative answers to obtain all names in a given zone. This is possible when such negative answers provide information on the previous and next names in a chain. [↩](#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":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/dnssec/","name":"DNSSEC"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/dnssec/enable-nsec3/","name":"NSEC3 support"}}]}
```

---

---
title: About
description: How multi-signer DNSSEC works with multiple DNS providers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# About

Multi-signer DNSSEC consists of two models that allow different authoritative DNS providers to serve the same zone and have DNSSEC enabled at the same time.

This means better compatibility with DNS features that require live-signing of DNS records (at query time), and also allows you to [migrate zones to Cloudflare without having to disable DNSSEC](https://developers.cloudflare.com/dns/dnssec/dnssec-active-migration/).

You can [set up multi-signer DNSSEC](https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/setup/) using either one of the models described in [RFC 8901 ↗](https://www.rfc-editor.org/rfc/rfc8901.html).

## How it works

Note

This is a simplified explanation to give you context and clarify what is involved in a [multi-signer DNSSEC setup](https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/setup/). For technical details refer to [RFC 8901 ↗](https://www.rfc-editor.org/rfc/rfc8901.html). To read more about DNSSEC, refer to [How DNSSEC works ↗](https://www.cloudflare.com/dns/dnssec/how-dnssec-works/).

Multi-signer DNSSEC looks into the chain of trust that is necessary for DNSSEC validation and leverages that to guarantee that validation is completed even when multiple providers are involved.

An example case where validation would otherwise be an issue is if a resolver has cached a [DNSKEY record set ↗](https://www.cloudflare.com/learning/dns/dns-records/dnskey-ds-records/) from one provider but receives a response signed by another provider.

To avoid issues in that case, when you set up multi-signer DNSSEC, you adjust:

1. The Zone Signing Keys (ZSK) that your DNS providers have in their DNSKEY record sets.
2. Who is responsible for the Secure Entry Point (SEP), Key Signing Keys (KSK), and Delegation Signer (DS) record.

When these configurations are adjusted in a way that (a) all involved providers have each other's public Zone Signing Keys (ZSK), and that (b) Delegation Signer (DS) records reference the necessary Key Signing Keys (KSK), then live-signing of zones by multiple providers is no longer a problem.

### Model 1

Whereas in both models all providers have each other's Zone Signing Keys (ZSK) added to their DNSKEY record set, in model 1, only one Key Signing Key (KSK) is used to sign such DNSKEY record sets. Management of this KSK and its reference by the DS record (that is, the Secure Entry Point) is the responsibility of the zone owner or only one provider (designated by the zone owner).

### Model 2

In model 2, on the other hand, each provider uses its own KSK to sign its own DNSKEY record set, and these KSKs are then referenced by the DS record (Secure Entry Point).

---

## What happens when multi-signer DNSSEC is on

When you turn on multi-signer DNSSEC on Cloudflare, the following changes occur:

1. **Internal flag**: Cloudflare sets an internal flag that allows you to add DNSKEY records to your zone.
2. **External ZSKs included**: When you add DNSKEY records from your secondary provider, Cloudflare includes them in the DNSKEY RRset.
3. **Signing with Cloudflare's KSK**: Cloudflare signs the external ZSKs with Cloudflare's KSK, creating a Multi-signer DNSSEC Model 2 RRset.
4. **CDS/CDNSKEY generation**: If you add your other provider's KSK (not required but recommended), Cloudflare produces CDS/CDNSKEY RRsets for compatibility with validation tools.

This configuration ensures that resolvers can validate responses from either provider, as all ZSK DNSKEYs are signed by the appropriate KSKs referenced in the DS records.

---

## Best practices

When setting up multi-signer DNSSEC, follow the best practices below to help you achieve a smooth deployment.

### Use model 2

Cloudflare recommends model 2 for multi-signer setups. In this model, each provider has their own KSK DNSKEY, resulting in two DS records (one for each provider). This provides better independence and flexibility.

### Understand DNSKEY flags

* **ZSKs (Zone Signing Keys)**: flag `256`
* **KSKs (Key Signing Keys)**: flag `257`

When exchanging keys between providers, ensure you are adding the correct key type (typically ZSKs) to the DNSKEY RRset.

### Adhere to TTLs

Always wait for the TTL duration after making changes to DNSKEYs and DS records before proceeding to the next step. This ensures that cached records expire before new records take effect, preventing validation failures.

### Verify provider compatibility

Not all DNS providers support adding external DNSKEYs to their DNSKEY RRset. Before starting a multi-signer migration:

* Verify that your other provider supports multi-signer DNSSEC.
* Confirm they can add Cloudflare's ZSK to their DNSKEY records.
* Test the configuration in a non-production environment if possible.

Some third-party providers may not support the required functionality.

### Test thoroughly

Multi-signer DNSSEC involves coordinating cryptographic keys across multiple providers. Before deploying to production:

1. Verify that both providers have each other's ZSKs in their DNSKEY RRsets.
2. Confirm that both DS records are present at the registrar.
3. Use DNSSEC validation tools to test resolution from both providers.
4. Monitor for validation errors during the transition period.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/dnssec/","name":"DNSSEC"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/dnssec/multi-signer-dnssec/","name":"Multi-signer DNSSEC"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/dnssec/multi-signer-dnssec/about/","name":"About"}}]}
```

---

---
title: Set up multi-signer DNSSEC
description: Configure multi-signer DNSSEC for your zone.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Set up multi-signer DNSSEC

This page explains how you can enable [multi-signer DNSSEC](https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/about/) with Cloudflare, using the [model 2](https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/about/#model-2) as described in [RFC 8901 ↗](https://www.rfc-editor.org/rfc/rfc8901.html).

## Before you begin

Note that:

* This process requires that your other DNS provider(s) also support multi-signer DNSSEC.
* Although you can complete a few steps via the dashboard, currently the whole process can only be completed using the API.
* Enabling **DNSSEC** and **Multi-signer DNSSEC** on the [**DNS Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings) page only replaces the first step in [1\. Set up Cloudflare zone](#1-set-up-cloudflare-zone). You still have to follow the rest of this tutorial to complete the setup.

## 1\. Set up Cloudflare zone

### Cloudflare as Primary (full setup)

If you use Cloudflare as a primary DNS provider, meaning that you manage your DNS records in Cloudflare, do the following:

* [ Dashboard ](#tab-panel-7927)
* [ API ](#tab-panel-7928)

1. In the Cloudflare dashboard, go to the **DNS Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings)
2. Select **Enable DNSSEC** and **Confirm**.

Note

For the purpose of this tutorial, you will update your registrar with the DS record later, in [Step 3](https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/setup/#3-set-up-registrar).

1. Also enable **Multi-signer DNSSEC** and **Multi-provider DNS**.
2. Go to the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page and create the following records at your zone apex (meaning you should use `@` in the record **Name** field):  
   * A [DNSKEY record](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#ds-and-dnskey) with the zone signing key(s) (ZSKs) of your external provider(s).  
   * An [NS record](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#ns) with your external provider nameservers.

1. Use the [Edit DNSSEC Status endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/edit/) to enable DNSSEC and activate multi-signer DNSSEC for your zone. Set `status` to `active` and `dnssec_multi_signer` to `true`, as in the following example.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Edit DNSSEC Status

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dnssec" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "status": "active",

    "dnssec_multi_signer": true

  }'


```

1. Add the ZSK(s) of your external provider(s) to Cloudflare by creating a DNSKEY record on your zone.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Create DNS Record

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "type": "DNSKEY",

    "name": "<ZONE_NAME>",

    "data": {

        "flags": 256,

        "protocol": 3,

        "algorithm": 13,

        "public_key": "<PUBLIC_KEY>"

    },

    "ttl": 3600

  }'


```

1. Add your external provider(s) nameservers as NS records on your zone apex.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Create DNS Record

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "type": "NS",

    "name": "<ZONE_NAME>",

    "content": "<NS_DOMAIN>",

    "ttl": 86400

  }'


```

1. Enable the usage of the nameservers you added in the previous step by using the API request below.

Warning

This step is required. Without turning on this setting, Cloudflare will ignore any `NS` records created on the zone apex. This means that responses to DNS queries made to the zone apex and requesting `NS` records will only contain Cloudflare nameservers.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone DNS Settings Write`
* `DNS Write`

Update DNS Settings

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_settings" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "multi_provider": true

  }'


```

### Cloudflare as Secondary

If you use Cloudflare as a secondary DNS provider, do the following:

* [ Dashboard ](#tab-panel-7925)
* [ API ](#tab-panel-7926)

1. In the Cloudflare dashboard, go to the **DNS Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings)
2. For **DNSSEC with Secondary DNS** select **Live signing**.

Note

For the purpose of this tutorial, you will update your registrar with the DS record later, in [Step 3](https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/setup/#3-set-up-registrar).

1. Also enable **Multi-signer DNSSEC**.
2. Add the zone signing key(s) (ZSKs) of your external provider(s) to a DNSKEY record at your primary DNS provider. This record should be transferred successfully to Cloudflare.
3. Add your external provider(s) nameservers as NS records on your zone apex at your primary DNS provider. These records should be transferred successfully to Cloudflare.

1. Use the [Edit DNSSEC Status endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/edit/) to enable DNSSEC and activate multi-signer DNSSEC for your zone. Set `status` to `active` and `dnssec_multi_signer` to `true`, as in the following example.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Edit DNSSEC Status

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dnssec" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "status": "active",

    "dnssec_multi_signer": true

  }'


```

1. Add the ZSK(s) of your external provider(s) to a DNSKEY record at your primary DNS provider. This record should be transferred successfully to Cloudflare.
2. Add your external provider(s) nameservers as NS records on your zone apex at your primary DNS provider. These records should be transferred successfully to Cloudflare.

## 2\. Set up external provider

1. Get Cloudflare's ZSK using either the API or a query from one of the assigned Cloudflare nameservers.

API example:

Terminal window

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/dnssec/zsk" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>"


```

Command line query example:

Terminal window

```

$ dig <ZONE_NAME> dnskey @<CLOUDFLARE_NAMESERVER> +noall +answer | grep 256


```

1. Add Cloudflare's ZSK that you fetched in the previous step to the DNSKEY record set of your external provider(s).
2. Add Cloudflare's nameservers to the NS record set at your external provider(s).

## 3\. Set up registrar

1. Add DS records to your registrar, one for each provider. You can see your Cloudflare DS record on the [**DNS Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings) page, under **DS Record**.
2. Update the nameserver settings at your registrar to include the nameservers of all providers you will be using for your multi-signer DNSSEC setup.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/dnssec/","name":"DNSSEC"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/dnssec/multi-signer-dnssec/","name":"Multi-signer DNSSEC"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/dnssec/multi-signer-dnssec/setup/","name":"Set up multi-signer DNSSEC"}}]}
```

---

---
title: Troubleshooting
description: Learn how to troubleshoot issues with DNSSEC
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

Learn more about how to troubleshoot issues with DNSSEC.

## Test DNSSEC with Dig

`Dig` is a command-line tool to query a nameserver for DNS records.

For instance, `dig` can ask a DNS resolver for the IP address of `www.cloudflare.com`:

Terminal window

```

dig www.cloudflare.com +short


```

```

198.41.215.162

198.41.214.162


```

The option `+short` outputs the result only.

Use `+dnssec` to verify that the DNS records are signed:

Terminal window

```

dig www.cloudflare.com +dnssec +short


```

```

198.41.214.162

198.41.215.162

A 13 3 300 20180927180434 20180925160434 35273 cloudflare.com. DYYZ/bhHSAIlpvu/HEUsxlzkC9NsswbCQ7dcfcuiNBrbhYV7k3AI8t46 QMnOlfhwT6jqsfN7ePV6Fwpym3B0pg==


```

In this example, the last line of output is the `RRSIG` record. `RRSIG` is the DNSSEC signature attached to the record. With the `RRSIG`, a DNS resolver determines whether a DNS response is trusted.

`Dig` can also retrieve the public key used to verify the DNS record, `DNSKEY`:

Terminal window

```

dig DNSKEY cloudflare.com +short


```

```

257 3 13 mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+ KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==

256 3 13 koPbw9wmYZ7ggcjnQ6ayHyhHaDNMYELKTqT+qRGrZpWSccr/lBcrm10Z 1PuQHB3Azhii+sb0PYFkH1ruxLhe5g==


```

A domain's DNS records are all signed with the same public key. Therefore, query for the apex domain (`cloudflare.com`) public key, not the subdomain (`www.cloudflare.com`) public key.

The DNS response includes two records:

* `DNSKEY` record **256** is the public key called zone signing key (ZSK). ZSKs are used to verify the DNS record signatures for `A`, `MX`, `CNAME`, `SRV`, etc.
* `DNSKEY` record **257** is called the key signing key (KSK). KSKs are used to verify the signatures of the `DNSKEY`, `CDS`, and `CDNSKEY` records.

Note

Details on how to verify the signatures with the public key are beyond the scope of this article.

When not using the `+short` option with `dig`, a DNS response is DNSSEC authenticated if the `ad` flag appears in the response header:

Terminal window

```

dig www.cloudflare.com


```

```

[...]

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 65326

;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

[...]

;; QUESTION SECTION:

;www.cloudflare.com.        IN  A

[...]

;; ANSWER SECTION:

www.cloudflare.com. 15  IN  A   198.41.215.162

www.cloudflare.com. 15  IN  A   198.41.214.162


```

---

## Troubleshoot DNSSEC validation using DNSViz

Note

DNSViz is a public, free online tool to visualize and help discover issues with your DNSSEC configuration and is **not** associated with Cloudflare.

To visualize and discover potential issues with DNSSEC:

1. Go to [https://dnsviz.net/ ↗](https://dnsviz.net/).
2. Enter a domain name in the text field that appears.
3. If DNSViz has never analyzed the site before, select **Analyze**.
4. If the site has been analyzed by DNSViz before, select **Update Now**.

### Example with missing or incorrect RRSIG record on authoritative nameserver

Below is an example of how dnsviz.net will display incorrect delegation when no valid DNSKEY records are provided by the authoritative nameserver to match the DS record published by the TLD nameserver:

![Incorrect delegation when no valid DNSKEY records are provided](https://developers.cloudflare.com/_astro/troubleshoot_dnssec-example_no_rrsig.PZ_zKLVg_19F4j2.webp) 

---

## View the DNSSEC chain of trust with Dig

Full verification of domain signatures (for example, `cloudflare.com`) involves verifying the key signing key at the top-level domain (for example, `.com`).

Similar verification is then performed by checking the key-signing key of `.com` at the root server level. DNSSEC root keys are distributed to DNS clients to complete the chain of trust.

When DNSSEC is enabled, a `DS` record is required at the registrar's DNS. The `DS` record contains a hash of the public key signing key as well as metadata about the key.

Use `dig` to find a `DS` record:

Terminal window

```

dig +short DS cloudflare.com


```

```

2371 13 2 32996839A6D808AFE3EB4A795A0E6A7A39A76FC52FF228B22B76F6D6 3826F2B9


```

When using the `+trace` option, `dig` confirms whether an answer is returned by the nameserver for `cloudflare.com` or the nameserver for `.com`. In this example, the `DS` record for `cloudflare.com` is returned by `e.gtld-servers.net`:

Terminal window

```

dig DS cloudflare.com +trace


```

```

[...]

cloudflare.com.     86400   IN  DS  2371 13 2 32996839A6D808AFE3EB4A795A0E6A7A39A76FC52FF228B22B76F6D6 3826F2B9

[...]

com.            172800  IN  NS  e.gtld-servers.net.

[...]

;; Received 1213 bytes from 2001:502:1ca1::30#53(e.gtld-servers.net) in 37 ms


```

An easier alternative to manually running the steps above is to use the third-party tool [DNSViz](#troubleshoot-dnssec-validation-using-dnsviz).

---

## Troubleshoot DNSSEC validation with Dig

Issues occur if authoritative DNS providers are changed without updating or removing old DNSSEC records at the registrar:

Terminal window

```

dig A brokendnssec.net @1.0.0.1


```

```

;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 10663


```

Confirm whether a `SERVFAIL` response is related to DNSSEC by running `dig` with the `+cd` option. The `+cd` option provides DNS results without any DNSSEC validation in place.

Terminal window

```

dig A brokendnssec.net @1.0.0.1 +dnssec +cd +short


```

```

104.20.49.61

104.20.48.61


```

In this example, DNSSEC is misconfigured if a proper DNS response is received when using the `+cd` option but queries using DNSSEC return a `SERVFAIL` response. This issue often happens when authoritative nameservers are changed but `DS` records are not updated. The issue can also occur if an attacker attempts to forge a response to a query.

---

## Delete remaining DNSKEY records after disabling DNSSEC

After disabling DNSSEC, DNSKEY records continue to appear in DNS queries and zone transfers. In the `disabled` state, Cloudflare still signs the zone and serves RRSIG, NSEC, and DNSKEY records. This is expected behavior and **not a misconfiguration or error**. Refer to [DNSSEC states](https://developers.cloudflare.com/dns/dnssec/dnssec-states/) and [RFC 8078 ↗](https://www.rfc-editor.org/rfc/rfc8078.html#section-4) for details.

However, some security vendors or audit tools may flag these DNSKEY records as problematic, reporting "DNSKEY record found but no DS record found" with a security outcome of "Provably Insecure". You can remove the DNSKEY records using the API.

### How to remove remaining DNSKEY records

Make sure DNSSEC is fully turned off

As a rule of thumb, after removing the DS record from your registrar, wait at least 1.5 times its [TTL](https://developers.cloudflare.com/dns/manage-dns-records/reference/ttl/) before removing the DNSKEY records. If the DS TTL is 24 hours, wait 36 hours.

Removing DNSKEY records while DNSSEC is still enabled will break DNS resolution.

Use the [Delete DNSSEC API](https://developers.cloudflare.com/api/resources/dns/subresources/dnssec/methods/delete/) to transition the zone to the `deleted` state. This stops all zone signing and removes all DNSSEC record types (RRSIG, NSEC, DNSKEY, CDS, and CDNSKEY):

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Delete DNSSEC records

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dnssec" \

  --request DELETE \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

For more information on DNSSEC states, refer to [DNSSEC states](https://developers.cloudflare.com/dns/dnssec/dnssec-states/).

### Verify DNSKEY removal

After removing the DNSKEY records, verify they no longer appear in DNS responses. An empty response confirms removal.

Terminal window

```

dig DNSKEY example.com +short


```

If DNSKEY records still appear, wait for the [time-to-live (TTL)](https://developers.cloudflare.com/dns/manage-dns-records/reference/ttl/) to expire. DNSKEY records typically have longer TTL values (often 3600 seconds or more), so propagation may take one hour or longer.

---

## Next steps

If a problem is discovered with DNSSEC implementation, contact the domain's registrar and confirm the DS record matches what the authoritative DNS provider has specified. If Cloudflare is the authoritative DNS provider, follow the instructions for [configuring DNSSEC with Cloudflare](https://developers.cloudflare.com/dns/dnssec/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/dnssec/","name":"DNSSEC"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/dnssec/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: Validation and keys
description: DNSSEC key types, rotation, and validation behavior.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Validation and keys

Refer to the sections below for an overview of some technical concepts and how they apply to Cloudflare DNSSEC. For broader content on DNSSEC, refer to [How DNSSEC works ↗](https://www.cloudflare.com/dns/dnssec/how-dnssec-works/).

## Chain of trust

DNSSEC validation follows a chain of trust from the root DNS servers to your zone:

1. A resolver queries your parent registry (for example, `.com`) for your DS record.
2. The DS record contains a hash of your Key Signing Key (KSK).
3. The resolver expects all Zone Signing Keys (ZSK) to be signed by that specific KSK.
4. If Cloudflare uses a different KSK, validation fails when resolvers query Cloudflare nameservers.

This is why you cannot simply keep your existing DS record when migrating to Cloudflare. The cryptographic chain of trust requires either:

* [Disabling DNSSEC](https://developers.cloudflare.com/dns/dnssec/) before migration and re-enabling it on Cloudflare
* Using the [multi-signer DNSSEC](https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/about/) approach to coordinate keys between providers.

---

## Automatic DS record updates

When you enable DNSSEC, Cloudflare automatically publishes **CDS** (Child Delegation Signer) and **CDNSKEY** (Child DNSKEY) records in your zone. These records automate the chain of trust management between your domain and the Top-Level Domain registry.

| Record      | Purpose                | Contents                                                                           |
| ----------- | ---------------------- | ---------------------------------------------------------------------------------- |
| **CDS**     | High-level instruction | A hashed version of the public key (same data as a DS record)                      |
| **CDNSKEY** | Public key instruction | The full public Key Signing Key (KSK) for the parent to generate its own DS record |

Registrars that support [RFC 8078 ↗](https://www.rfc-editor.org/rfc/rfc8078.html) periodically scan your domain for these records and automatically update the DS record at the registry level. This eliminates manual DS record management and ensures seamless key rollovers.

Note

Not all registrars support automatic CDS/CDNSKEY scanning. If your registrar does not support RFC 8078, you must manually add the DS record.

---

## DNSKEY flags

* **ZSKs (Zone Signing Keys)**: flag `256`
* **KSKs (Key Signing Keys)**: flag `257`

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/dnssec/","name":"DNSSEC"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/dnssec/validation-and-key-management/","name":"Validation and keys"}}]}
```

---

---
title: CNAME flattening
description: Resolve CNAME records at the zone apex to comply with DNS standards.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# CNAME flattening

CNAME flattening speeds up CNAME resolution and allows you to use a [CNAME record](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#cname) at your [zone apex](https://developers.cloudflare.com/dns/concepts/#zone-apex) (`example.com`).

Note

This functionality is also what allows you to use a [root custom domain](https://developers.cloudflare.com/pages/configuration/custom-domains/) with a Cloudflare Pages site.

## How it works

With CNAME flattening, Cloudflare finds the IP address that a CNAME points to. This process could involve a single lookup or multiple (if your CNAME points to another CNAME). Cloudflare then returns the final IP address instead of a CNAME record, helping DNS queries resolve faster.

For more details on the steps involved in CNAME flattening, review the [CNAME flattening diagram](https://developers.cloudflare.com/dns/cname-flattening/cname-flattening-diagram/) and refer to the [Cloudflare blog post ↗](https://blog.cloudflare.com/introducing-cname-flattening-rfc-compliant-cnames-at-a-domains-root/).

Note

For information about CNAME flattening in [Internal DNS](https://developers.cloudflare.com/dns/internal-dns/), refer to [internal DNS records](https://developers.cloudflare.com/dns/internal-dns/internal-zones/internal-dns-records/).

## Aspects to keep in mind

* CNAME flattening happens by default in some cases. Refer to [Setup](https://developers.cloudflare.com/dns/cname-flattening/set-up-cname-flattening/) for details.
* CNAME to a different Cloudflare account is prohibited and will result in [Error 1014: CNAME Cross-User Banned](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-1xxx-errors/error-1014/)
* If a CNAME target is being used to verify a domain for a third-party service, turning on [CNAME flattening for all CNAME records](https://developers.cloudflare.com/dns/cname-flattening/set-up-cname-flattening/#for-all-cname-records) may cause the verification to fail since the CNAME record itself will not be returned directly.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/cname-flattening/","name":"CNAME flattening"}}]}
```

---

---
title: Example diagram
description: Consider an example use case and the main steps involved in CNAME flattening.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Example diagram

With CNAME flattening, Cloudflare returns an IP address instead of the target hostname that a CNAME record points to. This process supports a few features and delivers better performance and flexibility, as mentioned in the [CNAME flattening concept page](https://developers.cloudflare.com/dns/cname-flattening/).

Consider the diagram below to have an overview of the steps that may be involved in CNAME flattening.

Note

Note that this is a simpler scenario. Cases where CNAME flattening is optional and/or the target hostname is not external to Cloudflare work differently.

## Example use case

* `domain.test` is a zone on Cloudflare and has the following CNAME record:

| Type  | Name        | Content              | TTL  |
| ----- | ----------- | -------------------- | ---- |
| CNAME | domain.test | external-origin.test | 3600 |

* `external-origin.test` is a zone on a different DNS provider and has the following A record:

| Type | Name                 | Content   | TTL  |
| ---- | -------------------- | --------- | ---- |
| A    | external-origin.test | 192.0.2.1 | 7200 |

In this case, the process to respond to queries for `domain.test` directly with the IP address can be represented by the following diagram:

flowchart BT
accTitle: CNAME flattening diagram
accDescr: Diagram of CNAME flattening process when there is a request for a domain in Cloudflare and the zone has a CNAME record at apex that points to an external A record.
  A((User)) <--query for <code>domain.test</code>--> B[Resolver] --> C
  C["Question:
  <code>domain.test IN A</code>"]
 subgraph Y[Cloudflare DNS]
 direction RL
  D{{Look up record}} --> G["Answer:
  <code>domain.test 3600 CNAME external-origin.test</code>

  This means that <code>domain.test</code> is a <code>CNAME</code> at the zone apex.
  Forced <code>CNAME</code> flattening is enabled."] --- H{{Resolve <code>external-origin.test</code>}}
  K{{Append answer with overwritten query name}} --> L["Answer:
  <code>domain.test 7200 IN A 192.0.2.1</code>"] --- M{Proxy status}
  M --Proxied--> O["Answer:
  <code>domain.test 300 IN A {$Cloudflare IP 1}</code>
  <code>domain.test 300 IN A {$Cloudflare IP 2}</code>"]
  M --DNS only--> N["Answer:
  <code>domain.test 3600 IN A 192.0.2.1</code>"]
 end

 subgraph Z [External DNS provider]
  J["Answer:
  <code>external-origin.test 7200 IN A 192.0.2.1</code>"]
 end

 C --> D
 H --- J --- K
 O --> B
 N --> B

## Aspects to consider

* If the CNAME record is proxied in Cloudflare, the answer is made up of multiple [Cloudflare IPs ↗](https://www.cloudflare.com/ips/) and its Time to Live (TTL) is set to `300`.
* If the CNAME record in Cloudflare is not proxied, the flattened answer consists of the IP address from the external DNS provider and its TTL corresponds to the lower value between the external record and the Cloudflare CNAME record.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/cname-flattening/","name":"CNAME flattening"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/cname-flattening/cname-flattening-diagram/","name":"Example diagram"}}]}
```

---

---
title: Setup
description: Configure CNAME flattening for your zone.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Setup

Note

If the CNAME target is on the same zone as the CNAME record, Cloudflare proceeds with CNAME flattening and ignores the **CNAME Flattening** setting.

## For your zone apex

CNAME flattening occurs by default for all plans when your domain uses a CNAME record for its zone apex (`example.com`, meaning the record **Name** is set to `@`).

## For all CNAME records

For zones on paid plans, you can choose to flatten all CNAME records. This option is useful for DNS-only (unproxied) CNAME records. [Proxied records](https://developers.cloudflare.com/dns/proxy-status/) are flattened by default as they return Cloudflare anycast IPs.

* [ Dashboard ](#tab-panel-7921)
* [ API ](#tab-panel-7922)

1. In the Cloudflare dashboard, go to the **DNS Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings)
2. Turn on the option **CNAME flattening for all CNAME records**.

Make a `PATCH` request to the [Update DNS Settings](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/methods/edit/) endpoint and set `flatten_all_cnames` to `true` in the request body.

Warning

If a CNAME target is being used to verify a domain for a third-party service, turning on [CNAME flattening for all CNAME records](https://developers.cloudflare.com/dns/cname-flattening/set-up-cname-flattening/#for-all-cname-records) may cause the verification to fail since the CNAME record itself will not be returned directly.

## Per record

Paid zones also have the option of flattening specific CNAME records.

If you use this option, a special [tag](https://developers.cloudflare.com/dns/manage-dns-records/reference/record-attributes/) `cf-flatten-cname` will be added to the respective flattened CNAME records in your zone file, allowing you to [export and import records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/) without losing this configuration.

* [ Dashboard ](#tab-panel-7919)
* [ API ](#tab-panel-7920)

1. On the [**DNS Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings) page, make sure that **CNAME flattening for all CNAME records** is turned off.
2. Go to the [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page and find the CNAME record you would like to flatten.
3. Select **Edit** and turn on the **Flatten** option.
4. Select **Save** to confirm.

Unavailable flatten option

For the following cases, **Flatten** will not be available:

* The record is at the [zone apex](#for-your-zone-apex).
* The record is already proxied, which means it will be flattened by default.
* **CNAME flattening for all CNAME records** is turned on, which means you cannot override it per record.

With the available [API endpoints](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/), specify the following for each CNAME record in the request body:

```

"settings": {

  "flatten_cname": true

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/cname-flattening/","name":"CNAME flattening"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/cname-flattening/set-up-cname-flattening/","name":"Setup"}}]}
```

---

---
title: Private origins (beta)
description: Connect Cloudflare's application services to your private network by proxying public hostnames to private origins.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Private origins (beta)

Proxy HTTP/HTTPS traffic from public hostnames to origins in your private network.

 Enterprise-only 

Connect Cloudflare's application services to your private network through secure tunnels. The CDN, WAF, Cache, and other proxied features apply to this traffic the same way they apply to traffic destined for public origins.

Getting started takes three steps. Follow the [setup guide](https://developers.cloudflare.com/dns/private-origins/set-up-via-cloudflare-wan/) to configure a tunnel, create a DNS record with [private network routing](https://developers.cloudflare.com/dns/private-origins/private-network-routing/), and verify end-to-end connectivity.

Closed beta

This feature is in closed beta. Contact your account team to request access.

---

## Resources

* [ Set up a private origin via Cloudflare WAN ](https://developers.cloudflare.com/dns/private-origins/set-up-via-cloudflare-wan/)
* [ Private network routing ](https://developers.cloudflare.com/dns/private-origins/private-network-routing/)
* [ Troubleshooting ](https://developers.cloudflare.com/dns/private-origins/troubleshooting/)

---

## Related products

**[Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/)** 

Connect your private network to Cloudflare with IPsec tunnels.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/private-origins/","name":"Private origins (beta)"}}]}
```

---

---
title: Private network routing
description: Route DNS record traffic to private origins through tunnels.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Private network routing

Private network routing allows you to proxy HTTP/HTTPS traffic from public hostnames to origins in your private network. When you enable this setting on a DNS record, Cloudflare routes traffic through your configured tunnel instead of over the public Internet.

For an end-to-end setup walkthrough using Cloudflare WAN (formerly Magic WAN) IPsec, refer to [Set up a private origin via Cloudflare WAN](https://developers.cloudflare.com/dns/private-origins/set-up-via-cloudflare-wan/).

Closed beta

This feature is in closed beta. Contact your account team to request access.

## Aspects to consider

Before you enable private network routing, consider the following:

* You need an active tunnel connection to Cloudflare through one of the supported on-ramp methods. Refer to [Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/on-ramps/) for further guidance.
* Private network routing is available for `A` (IPv4) and `AAAA` (IPv6) records only. Records must be [proxied](https://developers.cloudflare.com/dns/proxy-status/).
* If you have multiple `A` or `AAAA` records on the same name, and at least one of them has private network routing enabled, all records on that name will use private network routing. This is consistent with the [proxy status behavior](https://developers.cloudflare.com/dns/proxy-status/#mix-proxied-and-unproxied) in these cases.

## IP ranges

The following private address ranges are automatically detected:

| Range          | Description                                                         |
| -------------- | ------------------------------------------------------------------- |
| 10.0.0.0/8     | Private ([RFC 1918 ↗](https://www.rfc-editor.org/rfc/rfc1918.html)) |
| 172.16.0.0/12  | Private ([RFC 1918 ↗](https://www.rfc-editor.org/rfc/rfc1918.html)) |
| 192.168.0.0/16 | Private ([RFC 1918 ↗](https://www.rfc-editor.org/rfc/rfc1918.html)) |
| fc00::/7       | Private ([RFC 4193 ↗](https://www.rfc-editor.org/rfc/rfc4193.html)) |
| 100.64.0.0/10  | CGNAT ([RFC 6598 ↗](https://www.rfc-editor.org/rfc/rfc6598.html))   |

When you use an IP address from one of these ranges, the **Use private network routing** toggle turns on automatically. You can also turn it on manually for public IP addresses that are only reachable through your tunnel.

## Enable private network routing

Virtual networks

Traffic routes through your default virtual network. Selecting a specific virtual network is not supported.

* [ Dashboard ](#tab-panel-7975)
* [ API ](#tab-panel-7976)

1. In the Cloudflare dashboard, go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. Select **Add record** or select **Edit** on an existing `A` or `AAAA` record.
3. Enter the origin IP address.
4. Verify that **Proxy status** is enabled (orange cloud).
5. Turn on **Use private network routing**.  
For [private IP addresses](#ip-ranges) (for example, `10.0.0.50`), the toggle turns on automatically. For public IP addresses used with private infrastructure, turn on the toggle manually.
6. Select **Save**.

To create a record with private routing enabled, use a [POST request](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/) and set `private_routing` to `true`:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Create DNS Record

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "type": "A",

    "name": "app.example.com",

    "content": "10.0.0.50",

    "proxied": true,

    "private_routing": true

  }'


```

To enable private routing on an existing record, use a [PATCH request](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/edit/):

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DNS Write`

Update DNS Record

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$DNS_RECORD_ID" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "private_routing": true

  }'


```

### API field behavior

If you use the API to create or edit DNS records with private network routing, consider the following:

| Scenario                              | private\_routing value |
| ------------------------------------- | ---------------------- |
| Proxied A/AAAA record with private IP | Auto-set to true       |
| Proxied A/AAAA record with public IP  | Defaults to false      |
| Non-A/AAAA record types               | Field not supported    |

Also, if you manually set `private_routing: false` on a proxied `A`/`AAAA` record with private IP, the API will return an error.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/private-origins/","name":"Private origins (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/private-origins/private-network-routing/","name":"Private network routing"}}]}
```

---

---
title: Set up a private origin via Cloudflare WAN
description: Proxy public hostnames to private origins through a Cloudflare WAN IPsec tunnel.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Set up a private origin via Cloudflare WAN

This guide walks you through proxying public hostnames to origins on a private network. The private network is reachable through a [Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/) (formerly Magic WAN) IPsec tunnel. The CDN, WAF, Cache, and other proxied features apply to this traffic the same way they apply to traffic destined for public origins.

Closed beta

This feature is in closed beta. To request access, contact your Cloudflare account team.

## Before you begin

Confirm the following before you start:

* **Active Cloudflare WAN subscription**: This capability requires a Cloudflare WAN subscription on your account.
* **Access to private origins enabled on your account**: This is a separate entitlement from standard authoritative DNS access. Contact your Cloudflare account team to request access.
* **IPsec tunnels configured**: Set up two anycast IPsec tunnels for redundancy, each with a different Cloudflare anycast endpoint. Refer to [Configure tunnel endpoints](https://developers.cloudflare.com/cloudflare-wan/configuration/how-to/configure-tunnel-endpoints/). Two settings are important for this use case:  
   * Leave **Automatic return routing** disabled. It does not apply to the public-to-private origin traffic pattern, where requests originate on the Internet and reach your origin through Cloudflare's reverse proxy.  
   * Keep the default **Health check** settings (type `reply`, direction `bidirectional`, rate `mid`). These defaults are required for tunnel health to track correctly in this use case.
* **Static routes configured**: Add two static routes for the private prefix you want to reach — one per tunnel — with different priorities so traffic fails over to the backup tunnel if the primary goes down. For example, set priority `100` on the route through your primary tunnel and `101` on the route through your backup tunnel (lower numbers are higher priority). Refer to [Configure routes](https://developers.cloudflare.com/cloudflare-wan/configuration/how-to/configure-routes/).
* **Cloudflare Source IP set to a private range**: The Cloudflare Source IP is the IP that Cloudflare uses when sending proxied requests into your private network. If it is left as a public range, your network cannot route the return traffic back through the tunnel and requests time out. Refer to [Configure Cloudflare source IPs](https://developers.cloudflare.com/cloudflare-wan/configuration/how-to/configure-cloudflare-source-ips/).

## 1\. Verify your Cloudflare Source IP allocation

A misconfigured Cloudflare Source IP is the most common cause of failure. If the Source IP is left as a public range, the network where your origin lives has no return route and requests time out before reaching the application.

Go to [Configure Cloudflare source IPs](https://developers.cloudflare.com/cloudflare-wan/configuration/how-to/configure-cloudflare-source-ips/) and verify that the Source IP is set to a private range, such as `100.64.0.0/12` (the default) or another private `/12` you have selected.

## 2\. Create a DNS record with private network routing

Create an `A` or `AAAA` record that points to the private IP address of your origin, with proxy status enabled and **Use private network routing** turned on. This tells Cloudflare to send traffic for the hostname through your Cloudflare WAN tunnel instead of over the public Internet.

For the dashboard and API steps, refer to [Private network routing](https://developers.cloudflare.com/dns/private-origins/private-network-routing/).

## 3\. Verify end-to-end connectivity

After the DNS record is in place, validate the path from the Cloudflare network through your tunnel to the origin.

### Check tunnel health

In the Cloudflare dashboard, confirm that your IPsec tunnel is healthy. Refer to [Check tunnel health on the dashboard](https://developers.cloudflare.com/cloudflare-wan/configuration/common-settings/check-tunnel-health-dashboard/).

### Send a request from an external client

From a machine outside your private network, send an HTTPS request to the proxied hostname:

Terminal window

```

curl -v https://<YOUR_DOMAIN>/


```

A successful response confirms that Cloudflare accepted the request, applied your proxied features, and reached the origin through the tunnel.

### Confirm traffic on the origin

On the origin VM, verify that requests are arriving from the Cloudflare Source IP range. For example, to watch for incoming traffic from `100.64.0.0/12` on port `443`:

Terminal window

```

sudo tcpdump -n -i any 'src net 100.64.0.0/12 and dst port 443'


```

Replace `100.64.0.0/12` with the Source IP range configured for your account, and adjust the port to match the listener on your origin.

## Common pitfalls

| Symptom                                             | Cause and fix                                                                                                                                                                        |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Connection timeouts from clients                    | Cloudflare Source IP is set to a public range. Set it to a private /12.                                                                                                              |
| Request times out, no response on the origin        | The network where your origin lives has no return route for the Cloudflare Source IP range. Add a route that sends that range back through the tunnel.                               |
| Tunnel shows IKE established but health checks fail | ICMP is blocked on the path or the health check is misconfigured. Allow ICMP between the tunnel endpoints and confirm the health check direction is bidirectional and type is reply. |
| Traffic tries to route over the public Internet     | The **Use private network routing** toggle is not turned on for the DNS record. Edit the record and turn the toggle on.                                                              |

## Next steps

* [Configure tunnel health alerts](https://developers.cloudflare.com/cloudflare-wan/configuration/common-settings/configure-tunnel-health-alerts/) to get notified when a tunnel goes down.
* Review the [Private network routing](https://developers.cloudflare.com/dns/private-origins/private-network-routing/) reference for dashboard and API details.
* If you run into tunnel issues, refer to [Tunnel health troubleshooting](https://developers.cloudflare.com/cloudflare-wan/troubleshooting/tunnel-health/) and [IPsec troubleshooting](https://developers.cloudflare.com/cloudflare-wan/troubleshooting/ipsec-troubleshoot/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/private-origins/","name":"Private origins (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/private-origins/set-up-via-cloudflare-wan/","name":"Set up a private origin via Cloudflare WAN"}}]}
```

---

---
title: Troubleshooting
description: Troubleshoot common private network routing and private origin issues.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

## Error 1002: DNS points to prohibited IP

This error occurs when you proxy a private IP address without the necessary entitlement. Contact your account team to request access.

## Setting seems off but traffic routes through tunnel

Check for other records on the same name.

Private network routing applies per name, not per record. If you have multiple `A` or `AAAA` records on the same name and at least one of them has private network routing enabled, all records on that name will use private network routing.

## Traffic not reaching origin

If traffic is not reaching your private origin:

1. Verify your tunnel is active and healthy in the Cloudflare dashboard.
2. Confirm the origin IP is routable within your private network.
3. Check that `private_routing` is set to `true` on the DNS record.
4. Verify the record has proxy status enabled.

## Connection timeouts from clients

Cloudflare Source IP is set to a public range. Set it to a private `/12`. Refer to [Configure Cloudflare source IPs](https://developers.cloudflare.com/cloudflare-wan/configuration/how-to/configure-cloudflare-source-ips/).

## Request times out with no response on the origin

The network where your origin lives has no return route for the Cloudflare Source IP range. Add a route that sends that range back through the tunnel.

## Tunnel shows IKE established but health checks fail

ICMP is blocked on the path or the health check is misconfigured. Allow ICMP between the tunnel endpoints and confirm the health check direction is `bidirectional` and type is `reply`.

## Traffic tries to route over the public Internet

The **Use private network routing** toggle is not turned on for the DNS record. Edit the record and turn the toggle on. Refer to [Private network routing](https://developers.cloudflare.com/dns/private-origins/private-network-routing/) for dashboard and API steps.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/private-origins/","name":"Private origins (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/private-origins/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: Internal DNS (beta)
description: Resolve private hostnames within your network with Internal DNS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Internal DNS (beta)

Simplify private network management with Cloudflare DNS for your internal resources.

 Enterprise-only 

Manage DNS records that should only be accessible within your private network. Internal DNS [zones](https://developers.cloudflare.com/dns/internal-dns/internal-zones/) and [views](https://developers.cloudflare.com/dns/internal-dns/dns-views/) pair up with [Gateway resolver policies](https://developers.cloudflare.com/cloudflare-one/traffic-policies/resolver-policies/) so that you can control how a DNS query should be responded to according to query context, such as query source IP.

Note

Internal DNS is currently in beta. Using it on production traffic is at your own risk.

## Architecture overview

You can use different [connectivity options](https://developers.cloudflare.com/dns/internal-dns/connectivity/) to on-ramp your traffic to Cloudflare. Then, Cloudflare Gateway resolver acts as an interface between the DNS client and internal DNS zones.

Internal DNS zones do not get assigned Cloudflare nameservers and can only be queried via Cloudflare Gateway resolver.

flowchart LR
        accTitle: Internal DNS query overview
        accDescr: Diagram comparing internal DNS query with public DNS
        A[Client]
        subgraph Cloudflare account
        subgraph Gateway
				B[Default 1.1.1.1 resolver]
        X[Resolver policy selecting an internal DNS view]
        end
        subgraph Authoritative DNS
        Y[(Public DNS)]
				Z[(Internal DNS)]
        end
        end

			  C[Public resolver]

        B --Query--> Y
        X --Query + View ID--> Z
        A --Query--> B
				A --Query--> X
				C --Query--> Y

Internal DNS zones are grouped into DNS views, which are selected by the resolver policy you define. Views are usually logical groupings relevant to your organization, such as different geographical locations.

flowchart LR
        accTitle: Internal DNS views and zones
        accDescr: Diagram exemplifying Internal DNS views and zones relationship
        subgraph Internal DNS
        subgraph View 111 - London
        Y[Zone 600 <br /> example.local]
				Z[Zone 601 <br /> local]
        end
        subgraph View 110 - San Francisco
        X[Zone 101 <br /> example.com]
				B[Zone 100 <br /> example.local]
				S[Zone 102 <br /> com]
        end
				W[Zone 701 <br /> net]
				end

Internal DNS zones contain the [DNS records](https://developers.cloudflare.com/dns/internal-dns/internal-zones/internal-dns-records/) that should be used to resolve an internal DNS query. Also, if no internal record is found within a matching internal zone, Cloudflare will check if the matching internal zone is [referencing another internal zone](https://developers.cloudflare.com/dns/internal-dns/internal-zones/reference-zones/).

flowchart LR
        accTitle: Internal DNS zones and internal records
        accDescr: Diagram exemplifying Internal DNS zones and records relationship
        subgraph View 111 - London
				subgraph Zone 601 - local
				S["@ A 192.0.2.10"]
				T["ghi.example A 192.0.2.15"]
				end
        subgraph Zone 600 - example.local
				X["@ A 192.0.2.1"]
				Y["abc A 192.0.2.6"]
				Z["def A 192.0.2.9"]
				end
				end

In this example, a query for `ghi.example.local` routed to view ID 111 would go to zone 600, which presents the longest matching zone name (`example.local`). Zone 600 does not contain a record for `ghi` but, if it is referencing zone 601, Cloudflare will then look for the queried record within the reference zone.

## Resources

* [ Get started ](https://developers.cloudflare.com/dns/internal-dns/get-started/)
* [ Internal zones ](https://developers.cloudflare.com/dns/internal-dns/internal-zones/)
* [ Manage DNS views ](https://developers.cloudflare.com/dns/internal-dns/dns-views/)
* [ Connect to Gateway resolver ](https://developers.cloudflare.com/dns/internal-dns/connectivity/)
* [ Analytics and logs ](https://developers.cloudflare.com/dns/internal-dns/analytics/)

## Related products

**[Cloudflare Gateway](https://developers.cloudflare.com/cloudflare-one/traffic-policies/)** 

Set up policies to inspect DNS, Network, HTTP, and Egress traffic.

**[Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/)** 

Improve security and performance for your entire corporate networking, reducing cost and operation complexity.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/internal-dns/","name":"Internal DNS (beta)"}}]}
```

---

---
title: Analytics and logs
description: View analytics and logs for Internal DNS queries.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Analytics and logs

Internal DNS leverages [Gateway analytics](https://developers.cloudflare.com/cloudflare-one/insights/analytics/gateway/). Below you can find information about specific fields and different methods you can use to access this data.

## GraphQL

For detailed metrics, use the [GraphQL API](https://developers.cloudflare.com/analytics/graphql-api/). Refer to the GraphQL Analytics API documentation for guidance on how to [get started](https://developers.cloudflare.com/analytics/graphql-api/getting-started/).

The [fields](https://developers.cloudflare.com/analytics/graphql-api/getting-started/querying-basics/) added to cover Internal DNS are the following:

* `InternalDNSFallbackStrategy`: The fallback strategy applied to the internal DNS response. Empty if no fallback strategy was applied.
* `InternalDNSRCode`: The response code sent back by the internal DNS service.
* `InternalDNSViewID`: The view identifier that was sent to the internal DNS service.
* `InternalDNSZoneID`: The internal zone identifier returned by the internal DNS service.

## Logs

Leverage Logpush jobs for [Gateway DNS](https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/account/gateway%5Fdns/#internaldnsfallbackstrategy). For help setting up Logpush, refer to [Logpush](https://developers.cloudflare.com/logs/logpush/) documentation.

You can also set up [Logpush filters](https://developers.cloudflare.com/logs/logpush/logpush-job/filters/) to only push logs related to a specific [internal zone](https://developers.cloudflare.com/dns/internal-dns/internal-zones/) or [view](https://developers.cloudflare.com/dns/internal-dns/dns-views/) ID.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/internal-dns/","name":"Internal DNS (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/internal-dns/analytics/","name":"Analytics and logs"}}]}
```

---

---
title: Connect to Gateway resolver
description: Connect to the Internal DNS Gateway resolver.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Connect to Gateway resolver

To connect to Cloudflare Gateway resolver - which is [required to reach private resources in Internal DNS](https://developers.cloudflare.com/dns/internal-dns/#architecture-overview) \- you can use the following options:

* DNS endpoints supported with [DNS locations](https://developers.cloudflare.com/cloudflare-one/networks/resolvers-and-proxies/dns/locations/)  
   * DNS over UDP/TCP port 53 (IPv4 or IPv6)  
   * DNS over TLS  
   * DNS over HTTPS
* [Proxy Auto-Configuration (PAC) files](https://developers.cloudflare.com/cloudflare-one/networks/resolvers-and-proxies/proxy-endpoints/)
* [WARP device client](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/cloudflare-one-client/)
* [Clientless browser isolation](https://developers.cloudflare.com/cloudflare-one/remote-browser-isolation/setup/clientless-browser-isolation/#filter-dns-queries)
* [Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/zero-trust/cloudflare-gateway/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/internal-dns/","name":"Internal DNS (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/internal-dns/connectivity/","name":"Connect to Gateway resolver"}}]}
```

---

---
title: Manage DNS views
description: Manage DNS views to return different responses by network.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Manage DNS views

Internal DNS views are logical groupings of [internal DNS zones](https://developers.cloudflare.com/dns/internal-dns/internal-zones/). As explained in the [architecture overview](https://developers.cloudflare.com/dns/internal-dns/#architecture-overview), DNS views are referenced by [Gateway resolver policies](https://developers.cloudflare.com/cloudflare-one/traffic-policies/resolver-policies/) to define how a specific query should be resolved.

Refer to the sections below for details on how to manage your DNS views, or consider the [get started](https://developers.cloudflare.com/dns/internal-dns/get-started/) for a complete workflow.

## Configuration conditions

When setting up DNS views, observe the following conditions:

* DNS views can be empty, with no [internal zones](https://developers.cloudflare.com/dns/internal-dns/internal-zones/) linked to them.
* A DNS view cannot contain public DNS zones.1
* Each internal DNS zone name must be unique within a given DNS view.
* Each DNS view name must be unique within a given Cloudflare account.

1 DNS zones that contain public DNS records and are accessible by public resolvers.

## Create a view

* [ Dashboard ](#tab-panel-7933)
* [ API ](#tab-panel-7934)

1. In the Cloudflare dashboard, go to the **Internal DNS** page.  
[ Go to **Internal DNS** ](https://dash.cloudflare.com/?to=/:account/internal-dns)
2. Go to **Internal DNS Views**.
3. Select **Create a view**.
4. Give your view a descriptive name.
1. Select **Manage zones** to add zones to your view. Select the internal zones that should be used to resolve queries sent by Gateway resolver to this view.
2. Choose **Save** to confirm.

Use the [Create Internal DNS View](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/account/subresources/views/methods/create/) endpoint. For each view you create, list all the internal zones that should be grouped under that view.

## Delete a view

DNS views can be deleted even if they still have internal zones linked to them. The internal DNS zones will continue to exist but will be unlinked once the view is deleted.

It is also possible to delete a DNS view that is being referenced by a Gateway resolver policy. In this case, queries matching the policy will return SERVFAIL.

* [ Dashboard ](#tab-panel-7931)
* [ API ](#tab-panel-7932)

1. In the Cloudflare dashboard, go to the **Internal DNS** page.  
[ Go to **Internal DNS** ](https://dash.cloudflare.com/?to=/:account/internal-dns)
2. Go to **Internal DNS Views**.
3. Find the view you want to delete.
4. Select the three dots in the corresponding row and choose _Delete_.
5. In the confirmation dialog, select **Delete** again to proceed.

Use the [Delete Internal DNS View](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/account/subresources/views/methods/delete/) endpoint.

## Other API actions

* [Update a DNS view](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/account/subresources/views/methods/edit/) (`PATCH`)
* [Get view details](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/account/subresources/views/methods/get/) (`GET`)
* [List DNS views](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/account/subresources/views/methods/list/) (`GET`)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/internal-dns/","name":"Internal DNS (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/internal-dns/dns-views/","name":"Manage DNS views"}}]}
```

---

---
title: Get started
description: Set up Internal DNS for private name resolution.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

Follow this guide to get started with Internal DNS.

Note

Internal DNS is currently in beta. Using it on production traffic is at your own risk.

## Before you begin

* Make sure you have an Enterprise account with access to [Gateway resolver policies](https://developers.cloudflare.com/cloudflare-one/traffic-policies/resolver-policies/) and [Internal DNS](https://developers.cloudflare.com/dns/internal-dns/).
* Consider the different ways in which you can [connect to Gateway resolver](https://developers.cloudflare.com/dns/internal-dns/connectivity/).  
Warning  
If using WARP, make sure your internal DNS zones or their TLDs are not listed in your [Local Domain Fallback configuration](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/cloudflare-one-client/configure/route-traffic/local-domains/). Otherwise, DNS queries for a matching domain will be sent to the local DNS server specified in the fallback, instead of being sent to Cloudflare.
* If you will be using an API token for authentication, make sure you have the following permissions:

API token configuration

**Permissions**

* _Account_ \- _DNS Views_ \- _Edit_
* _Zone_ \- _DNS_ \- _Edit_
* _Account_ \- _Account Settings_ \- _Edit_
* _Zone_ \- _DNS Settings_ \- _Edit_
* _Zone_ \- _Zone_ \- _Edit_

**Account Resources**

* _Include_ \- _(Your account)_

**Zone Resources**

* _Include_ \- _All zones_

## 1\. Set up your internal DNS zone

* [ Dashboard ](#tab-panel-7939)
* [ API ](#tab-panel-7940)

1. In the Cloudflare dashboard, go to the **Internal DNS** page.  
[ Go to **Internal DNS** ](https://dash.cloudflare.com/?to=/:account/internal-dns)
2. Select **Create an internal zone**.
3. Give your internal zone a name.

Internal zone configuration conditions

* Internal zones can contain the same [DNS record types](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/) that Cloudflare supports for public zones.
* An internal zone can have the same name as a public zone in the same account.
* Each internal zone can be linked to multiple [views](https://developers.cloudflare.com/dns/internal-dns/dns-views/).1
* There can be several internal zones with the same name in one account. However, two internal zones with the same name cannot be linked to the same view.
* Internal zones are not subject to any top-level domain (TLD) restrictions. This means that an internal zone can be created if its TLD is not registered publicly (for example, `xyz.local`), if it is created on the TLD itself (`local`), or even if on the root (`.`).

1 Logical groupings of internal DNS zones that are referenced by Gateway resolver policies to define how a specific query should be resolved.

1. Add DNS records to your internal zone using your preferred option:
* [Import](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/) a formatted BIND file.
* Select **Add a record** and choose **Create** under the record type you want to add. Refer to [DNS record types](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/) for details.
1. Repeat this process for each internal zone you wish to add.

Note

Creating multiple internal DNS records in batch is currently only supported via API.

1. Use the [Create Zone](https://developers.cloudflare.com/api/resources/zones/methods/create/) endpoint to create an [internal zone](https://developers.cloudflare.com/dns/internal-dns/internal-zones/). Specify your account ID and set the `type` to `internal`.

Internal zone configuration conditions

* Internal zones can contain the same [DNS record types](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/) that Cloudflare supports for public zones.
* An internal zone can have the same name as a public zone in the same account.
* Each internal zone can be linked to multiple [views](https://developers.cloudflare.com/dns/internal-dns/dns-views/).1
* There can be several internal zones with the same name in one account. However, two internal zones with the same name cannot be linked to the same view.
* Internal zones are not subject to any top-level domain (TLD) restrictions. This means that an internal zone can be created if its TLD is not registered publicly (for example, `xyz.local`), if it is created on the TLD itself (`local`), or even if on the root (`.`).

1 Logical groupings of internal DNS zones that are referenced by Gateway resolver policies to define how a specific query should be resolved.

Example

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Zone Edit`
* `Zone DNS Edit`

Create Zone

```

curl "https://api.cloudflare.com/client/v4/zones" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "account": {

        "id": "<ACCOUNT_ID>"

    },

    "name": "<ZONE_NAME>",

    "type": "internal"

  }'


```

1. Add DNS records to your internal zone using your preferred option:
* [Import](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/import/) a formatted BIND file. Refer to the [DNS records how-to](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/) for guidance.
* Use other API endpoints, such as [/batch](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/batch/), to manage DNS records. Refer to [Batch record changes](https://developers.cloudflare.com/dns/manage-dns-records/how-to/batch-record-changes/#use-the-api) for details.
1. Repeat this process for each internal zone you wish to add.

### (Optional) Reference a zone from another zone

During an [internal DNS query resolution](https://developers.cloudflare.com/dns/internal-dns/#architecture-overview), if no internal record is found within a matching internal zone, Cloudflare will check if the matching internal zone is referencing another internal zone. Successive references can be followed with a maximum of five references in a chain.

For details, refer to [reference zones](https://developers.cloudflare.com/dns/internal-dns/internal-zones/reference-zones/).

* [ Dashboard ](#tab-panel-7941)
* [ API ](#tab-panel-7942)

1. In the Cloudflare dashboard, go to the **Internal DNS** page.  
[ Go to **Internal DNS** ](https://dash.cloudflare.com/?to=/:account/internal-dns)
2. Select a zone.
3. Within the selected zone, go to **Reference zone**.
4. Select **Add reference zone**.
5. Find the zone you want to use as reference and choose **Select** in the respective row.

1. Use the [Update DNS settings](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/methods/edit/) endpoint to add a reference from an internal zone to another internal zone. In `--json`, specify the `internal_dns` object with the parameter `reference_zone_id`.

In the following example, internal zone A (ID `8a904aeb565c42cfa207d98f6edea2f3`) is referencing internal zone B (ID `8e64c6fb4b514f3faf64de81efc11e51`).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone DNS Settings Write`
* `DNS Write`

Update DNS Settings

```

curl "https://api.cloudflare.com/client/v4/zones/8a904aeb565c42cfa207d98f6edea2f3/dns_settings" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "internal_dns": {

        "reference_zone_id": "8e64c6fb4b514f3faf64de81efc11e51"

    }

  }'


```

## 2\. Link your internal zone to a view

Since the resolver policy will require a [DNS view](https://developers.cloudflare.com/dns/internal-dns/dns-views/), you must have at least one view to be able to route requests to internal zones.

* [ Dashboard ](#tab-panel-7937)
* [ API ](#tab-panel-7938)

1. In the Cloudflare dashboard, go to the **Internal DNS** page.  
[ Go to **Internal DNS** ](https://dash.cloudflare.com/?to=/:account/internal-dns)
2. Go to **Internal DNS Views**.
3. Select **Create a view**.
4. Give your view a descriptive name.

DNS view configuration conditions

* DNS views can be empty, with no [internal zones](https://developers.cloudflare.com/dns/internal-dns/internal-zones/) linked to them.
* A DNS view cannot contain public DNS zones.1
* Each internal DNS zone name must be unique within a given DNS view.
* Each DNS view name must be unique within a given Cloudflare account.

1 DNS zones that contain public DNS records and are accessible by public resolvers.

1. Select **Manage zones** to add zones to your view. Select the internal zones that should be used to resolve queries sent by Gateway resolver to this view.
2. Choose **Save** to confirm.

1. Use the [Create Internal DNS View](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/account/subresources/views/methods/create/) endpoint. For each view you create, list all the internal zones that should be grouped under that view.

DNS view configuration conditions

* DNS views can be empty, with no [internal zones](https://developers.cloudflare.com/dns/internal-dns/internal-zones/) linked to them.
* A DNS view cannot contain public DNS zones.1
* Each internal DNS zone name must be unique within a given DNS view.
* Each DNS view name must be unique within a given Cloudflare account.

1 DNS zones that contain public DNS records and are accessible by public resolvers.

## 3\. Configure Gateway policies

Note

The Gateway configuration must exist within the same Cloudflare account where the internal zone exists.

Besides selecting an internal DNS view when setting up your resolver policies, you can also enable the **fallback through public DNS** option.

* [ Dashboard ](#tab-panel-7935)
* [ API ](#tab-panel-7936)

1. In [Cloudflare One ↗](https://one.dash.cloudflare.com/), go to **Traffic policies** \> **Firewall policies** \> **Resolver policies**.
2. Select **Add a policy** and enter a name and description.
3. Create an expression for the traffic you wish to route. For guidance about selectors, operators, and values, refer to [Gateway resolver policies](https://developers.cloudflare.com/cloudflare-one/traffic-policies/resolver-policies/#selectors).
4. Select **Use Internal DNS**. Choose the view that queries matching the expression should be sent to.
5. (Optional) Adjust the option to **Fallback through public DNS** according to your use case.
* Off: Gateway DNS resolver returns the response as-is to the client.
* On: In case the response from the internal zone is REFUSED, NXDOMAIN, or a response with a CNAME type, Gateway DNS resolver sends the query to Cloudflare 1.1.1.1 public resolver and tries to resolve the query via public DNS.
1. Select **Create policy** to confirm.

Use the API endpoints under [Zero Trust > Gateway > Rules](https://developers.cloudflare.com/api/resources/zero%5Ftrust/subresources/gateway/subresources/rules/) to set up resolver policies. For guidance about selectors, operators, and values, refer to [Gateway](https://developers.cloudflare.com/cloudflare-one/traffic-policies/resolver-policies/#selectors).

Use the rule settings object to define `resolve_dns_internally`, specifying `view_id` and `fallback` option. The fallback options behave as follows:

* `none`: Gateway DNS resolver returns the response as-is to the client.
* `public_dns`: In case the response from the internal zone is REFUSED, NXDOMAIN, or a response with a CNAME type, Gateway DNS resolver sends the query to Cloudflare 1.1.1.1 public resolver and tries to resolve the query via public DNS.

Once you add the Gateway resolver policy, it will be listed in the respective internal view under **Resolver policies referencing this view**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/internal-dns/","name":"Internal DNS (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/internal-dns/get-started/","name":"Get started"}}]}
```

---

---
title: Internal zones
description: Explore internal DNS zones in Cloudflare. These zones organize DNS records for resources accessible only within your private network, queried via Cloudflare Gateway.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Internal zones

Internal DNS zones are groupings of internal DNS records. While [public DNS records](https://developers.cloudflare.com/dns/manage-dns-records/) contain information about resources that you want to make available to the public Internet, [internal DNS records](https://developers.cloudflare.com/dns/internal-dns/internal-zones/internal-dns-records/) allow you to manage resources that should only be available within your private network.

Refer to [Manage internal zones](https://developers.cloudflare.com/dns/internal-dns/internal-zones/setup/) for a full list of configuration conditions and step-by-step instructions.

Internal DNS zones do not get assigned Cloudflare nameservers and can only be queried via [Cloudflare Gateway](https://developers.cloudflare.com/cloudflare-one/traffic-policies/resolver-policies/) when linked to a [DNS view](https://developers.cloudflare.com/dns/internal-dns/dns-views/). The Gateway configuration must exist within the same Cloudflare account where the internal zone exists.

## Resources

* [ Manage internal zones ](https://developers.cloudflare.com/dns/internal-dns/internal-zones/setup/)
* [ Manage internal DNS records ](https://developers.cloudflare.com/dns/internal-dns/internal-zones/internal-dns-records/)
* [ Reference zones ](https://developers.cloudflare.com/dns/internal-dns/internal-zones/reference-zones/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/internal-dns/","name":"Internal DNS (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/internal-dns/internal-zones/","name":"Internal zones"}}]}
```

---

---
title: Manage internal DNS records
description: Manage internal DNS records in Cloudflare. Learn about supported DNS record types and CNAME flattening.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Manage internal DNS records

Internal zones can contain the same [DNS record types](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/) that Cloudflare supports for public zones.

You can manage internal DNS records in the same way as you would manage public DNS records, with the difference that [proxy status](https://developers.cloudflare.com/dns/proxy-status/) does not apply to internal DNS records.

Refer to [Manage DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) or to the [API documentation](https://developers.cloudflare.com/api/resources/dns/subresources/records/) for further guidance.

## CNAME flattening in Internal DNS

With [CNAME flattening](https://developers.cloudflare.com/dns/cname-flattening/), Cloudflare finds the final target content that a CNAME points to and then returns this content instead of a CNAME record. With Internal DNS, CNAME flattening is applied by default and cannot be turned off.

Cloudflare will try to flatten the CNAME record considering both the specified [DNS view](https://developers.cloudflare.com/dns/internal-dns/dns-views/) and any existing [reference zones](https://developers.cloudflare.com/dns/internal-dns/internal-zones/reference-zones/). If the reference zone then has another CNAME, the record will again be considered from the perspective of the original view.

Example

* Query for the `A` record on `abc.example.local` with view ID 111.
* Zone 600 references zone 700, which is not linked to any view.

flowchart LR
accTitle: Internal DNS zones and CNAME flattening example
accDescr: Diagram exemplifying Internal DNS zones and containing CNAME and A records

subgraph Internal DNS
subgraph Zone 700 - net
A["@ A 192.0.2.10"]
B["xyz CNAME def.example.local"]
end
subgraph View 111 - London
subgraph Zone 600 - example.local
X["@ A 192.0.2.1"]
Y["abc CNAME xyz.net"]
U["def TXT 15192-51"]
Z["def A 192.0.2.9"]
end
end
end

After finding the CNAME record that points to `xyz.net`, Cloudflare cannot resolve it within zone 600\. However, since this zone is referencing zone 700, this will be considered in the resolution.

The record in zone 700 points to `def.example.local`, which Cloudflare will then try to resolve in the original view. As an `A` record can be found for `def.example.local`, Cloudflare will return the corresponding IP address - in this example, `192.0.2.9`.

If it is not possible to flatten the CNAME record, the following will happen:

1. The CNAME record is returned to [Gateway resolver](https://developers.cloudflare.com/dns/internal-dns/#architecture-overview) as-is.
2. Gateway resolver will process the returned record, depending on the **Fallback through public DNS** configuration:  
   * On: Gateway will try to resolve the query by sending it to Cloudflare's public DNS resolver ([1.1.1.1](https://developers.cloudflare.com/1.1.1.1/)).  
   * Off: Gateway will return the response as-is to the client.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/internal-dns/","name":"Internal DNS (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/internal-dns/internal-zones/","name":"Internal zones"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/internal-dns/internal-zones/internal-dns-records/","name":"Manage internal DNS records"}}]}
```

---

---
title: Reference zones
description: Learn about reference zones. Cloudflare Internal DNS allows zones to reference others for query resolution when no direct record is found.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Reference zones

During an [internal DNS query resolution](https://developers.cloudflare.com/dns/internal-dns/#architecture-overview), if no internal record is found within a matching internal zone, Cloudflare will check if the matching internal zone is referencing another internal zone. Successive references can be followed with a maximum of five references in a chain.

Note

A wildcard record (`*.example.local`) in the matching internal zone will take precedence over an exact match in a reference zone.

## Configuration conditions

* Each internal zone can only reference one other zone.
* The same zone can be referenced by multiple internal zones.
* Public zones cannot be used as reference zones.
* Reference zones do not have to be linked to the same [DNS view](https://developers.cloudflare.com/dns/internal-dns/dns-views/) as the zone referencing them. They may also not be linked to any view at all.

## Set up

* [ Dashboard ](#tab-panel-7943)
* [ API ](#tab-panel-7944)

1. In the Cloudflare dashboard, go to the **Internal DNS** page.  
[ Go to **Internal DNS** ](https://dash.cloudflare.com/?to=/:account/internal-dns)
2. Select a zone.
3. Within the selected zone, go to **Reference zone**.
4. Select **Add reference zone**. If your zone already has a reference zone set up, you must first remove it. As explained in the [configuration conditions](#configuration-conditions), each internal zone can only reference one other zone at a time.
5. Find the zone you want to use as reference and choose **Select** in the respective row.

Use the [Update DNS settings](https://developers.cloudflare.com/api/resources/dns/subresources/settings/subresources/zone/methods/edit/) endpoint. In `--json`, specify the `internal_dns` object with the parameter `reference_zone_id`.

In the following example, internal zone A (ID `8a904aeb565c42cfa207d98f6edea2f3`) is referencing internal zone B (ID `8e64c6fb4b514f3faf64de81efc11e51`).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone DNS Settings Write`
* `DNS Write`

Update DNS Settings

```

curl "https://api.cloudflare.com/client/v4/zones/8a904aeb565c42cfa207d98f6edea2f3/dns_settings" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "internal_dns": {

        "reference_zone_id": "8e64c6fb4b514f3faf64de81efc11e51"

    }

  }'


```

A third zone (C) could also point to zone B as a reference, but zone A cannot add another zone as a reference while also having zone B configured as its reference zone.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/internal-dns/","name":"Internal DNS (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/internal-dns/internal-zones/","name":"Internal zones"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/internal-dns/internal-zones/reference-zones/","name":"Reference zones"}}]}
```

---

---
title: Manage internal zones
description: Understand how to set up and manage internal DNS zones with Cloudflare. Explore configuration conditions, zone creation, and available API endpoints.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Manage internal zones

Refer to the following sections to learn how to manage your [internal DNS zones](https://developers.cloudflare.com/dns/internal-dns/internal-zones/).

## Configuration conditions

When setting up internal zones, observe the following conditions:

* Internal zones can contain the same [DNS record types](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/) that Cloudflare supports for public zones.
* An internal zone can have the same name as a public zone in the same account.
* Each internal zone can be linked to multiple [views](https://developers.cloudflare.com/dns/internal-dns/dns-views/).1
* There can be several internal zones with the same name in one account. However, two internal zones with the same name cannot be linked to the same view.
* Internal zones are not subject to any top-level domain (TLD) restrictions. This means that an internal zone can be created if its TLD is not registered publicly (for example, `xyz.local`), if it is created on the TLD itself (`local`), or even if on the root (`.`).

1 Logical groupings of internal DNS zones that are referenced by Gateway resolver policies to define how a specific query should be resolved.

## Create an internal zone

* [ Dashboard ](#tab-panel-7945)
* [ API ](#tab-panel-7946)

1. In the Cloudflare dashboard, go to the **Internal DNS** page.  
[ Go to **Internal DNS** ](https://dash.cloudflare.com/?to=/:account/internal-dns)
2. Select **Create an internal zone**.
3. Give your internal zone a name.
1. Add DNS records to your internal zone using your preferred option:
* [Import](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/) a formatted BIND file.
* Select **Add a record** and choose **Create** under the record type you want to add. Refer to [DNS record types](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/) for details.
1. Repeat this process for each internal zone you wish to add.

Note

Creating multiple internal DNS records in batch is currently only supported via API.

1. Use the [Create Zone](https://developers.cloudflare.com/api/resources/zones/methods/create/) endpoint to create an [internal zone](https://developers.cloudflare.com/dns/internal-dns/internal-zones/). Specify your account ID and set the `type` to `internal`.

Example

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Zone Edit`
* `Zone DNS Edit`

Create Zone

```

curl "https://api.cloudflare.com/client/v4/zones" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "account": {

        "id": "<ACCOUNT_ID>"

    },

    "name": "<ZONE_NAME>",

    "type": "internal"

  }'


```

1. Add DNS records to your internal zone using your preferred option:
* [Import](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/import/) a formatted BIND file. Refer to the [DNS records how-to](https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/) for guidance.
* Use other API endpoints, such as [/batch](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/batch/), to manage DNS records. Refer to [Batch record changes](https://developers.cloudflare.com/dns/manage-dns-records/how-to/batch-record-changes/#use-the-api) for details.
1. Repeat this process for each internal zone you wish to add.

## Other API actions

The API endpoints to manage internal zones are the same as for managing public zones. The main difference is that the zone type must be set to `internal`. Refer to the API documentation below for details:

* [Update an internal zone](https://developers.cloudflare.com/api/resources/zones/methods/edit/) (`PATCH`)
* [Get internal zone details](https://developers.cloudflare.com/api/resources/zones/methods/get/) (`GET`)
* [List internal zones](https://developers.cloudflare.com/api/resources/zones/methods/list/) (`GET`)
* [Delete an internal zone](https://developers.cloudflare.com/api/resources/zones/methods/delete/) (`DELETE`)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/internal-dns/","name":"Internal DNS (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/internal-dns/internal-zones/","name":"Internal zones"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/internal-dns/internal-zones/setup/","name":"Manage internal zones"}}]}
```

---

---
title: DNS Firewall
description: Protect and accelerate authoritative nameservers with DNS-level caching and DDoS mitigation.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNS Firewall

Speed up and protect entire authoritative nameservers

 Enterprise-only paid add-on 

Cloudflare DNS Firewall proxies all DNS queries to your nameservers through Cloudflare’s global network. This action protects upstream nameservers from DDoS attacks and reduces load by caching DNS responses.

![Diagram showing protection provided by DNS Firewall. For more details, read further.](https://developers.cloudflare.com/_astro/dns-firewall-overview.DCpibQR6_Z18bd30.webp) 

DNS Firewall is for customers who need to speed up and protect entire authoritative nameservers. If you need to speed up and protect individual zones, refer to Cloudflare DNS [Setups](https://developers.cloudflare.com/dns/zone-setups/).

---

## How DNS Firewall works

When a DNS query for your domain takes place:

1. Queries go to the Cloudflare data center that is closest to the website visitor. This is determined by the location of the DNS resolver.
2. Cloudflare tries to return a DNS response from cache.
3. If the response is not available in cache, Cloudflare queries the upstream authoritative nameservers.
4. After returning the response from the nameservers, Cloudflare temporarily caches it for subsequent DNS queries.

---

## Benefits

DNS Firewall provides the following benefits while allowing your organization total control over your authoritative nameservers:

* DDoS mitigation
* High availability
* Global distribution
* Enhanced performance
* Bandwidth savings
* [Rate limiting per data center](https://developers.cloudflare.com/dns/dns-firewall/setup/#additional-options)
* Minimum and maximum cache TTL specification
* DNS [ANY ↗](https://datatracker.ietf.org/doc/html/rfc8482) query type block

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/dns-firewall/","name":"DNS Firewall"}}]}
```

---

---
title: Analytics and logs
description: Access DNS Firewall query analytics and configure Logpush for DNS logs.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Analytics and logs

Consider the sections below to learn how to access analytics and logs for your DNS Firewall.

## Analytics

DNS Firewall analytics allow you to evaluate data about DNS queries to your account.

### Availability and limits

The historical data available covers 62 days and the maximum time interval you can get data for is also 62 days.

### Dashboard

For a quick summary, view your DNS Firewall analytics on the dashboard. The DNS analytics dashboard contains [four main panels](#panels). The filters and time frame that you specify at the top of the page apply to all of them.

In the Cloudflare dashboard, go to the **DNS Firewall Analytics** page.

[ Go to **Analytics** ](https://dash.cloudflare.com/?to=/:account/dns-firewall/analytics) 

#### Available dimensions

* Query name
* Query type (same as DNS record type)
* Cluster
* Cluster IP
* Response code
* Response reason (refer to [descriptions](#response-reasons) below)
* Response cached (cached or uncached)
* Response stale (stale or fresh)
* Data center
* Source IP
* Upstream nameserver IP
* Protocol (UDP or TCP)
* IP version (IPv4 or IPv6)

#### Panels

The filters and time frame that you specify at the top of the page apply to all of the available panels.

* **Query summary**: the number of queries and their distribution over time. This information is segmented by each of the [available dimensions](#available-dimensions). You can select the dimensions through the different tabs above the graph and quickly filter for or exclude a certain value from the results by hovering over it and selecting **Filter** or **Exclude**.
* **Query statistics**: an overview of query metrics. Namely, **Total queries**, **Cached queries**, **Uncached queries**, and **Stale cache queries**.  
Processing time and response time  
Processing time refers to the total time taken to handle a query within DNS Firewall, meaning cached queries served directly from Cloudflare's servers. For uncached queries, the metric used is response time, which considers the time to get the answers from your upstream nameservers. The processing and response times are displayed in milliseconds.  
90th percentile (p90)  
 Aside from the average for both processing and response times, `p90` values show you the maximum time that 90% of queries took to resolve. For example, if the p90 is 1 millisecond, it means 90% of the queries were resolved in 1 millisecond or less.
* **DNS queries by data center**: a map indicating which Cloudflare data centers have handled DNS queries to your account. You can also find a list of the top ten results and quickly filter for or exclude a certain data center from the results by hovering over it and selecting **Filter** or **Exclude**.
* **Top query statistics**: a breakdown of the top queries grouped by the [available dimensions](#available-dimensions). You can expand each card to list more results and search for specific values.

### GraphQL

Use the [GraphQL API](https://developers.cloudflare.com/analytics/graphql-api/) to access DNS Firewall analytics. Refer to the GraphQL Analytics API documentation for guidance on how to [get started](https://developers.cloudflare.com/analytics/graphql-api/getting-started/).

The DNS Firewall analytics has two [schemas](https://developers.cloudflare.com/analytics/graphql-api/getting-started/querying-basics/):

* `dnsFirewallAnalyticsAdaptive`: Retrieve information about individual DNS Firewall queries.
* `dnsFirewallAnalyticsAdaptiveGroups`: Get reports on aggregate information only.

### API Legacy

You can also use the DNS Firewall API [reports endpoint](https://developers.cloudflare.com/api/resources/dns%5Ffirewall/subresources/analytics/subresources/reports/).

---

## Logs

You can [set up Logpush](https://developers.cloudflare.com/logs/logpush/) to deliver [DNS Firewall logs](https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/account/dns%5Ffirewall%5Flogs/) to a storage service, SIEM, or log management provider.

## Response reasons

When analyzing why Cloudflare DNS Firewall responded in one way or another to a specific query, consider the `responseReason` log field.

The following table provides a description for each of the values that might be returned as a response reason:

| Value                     | Description                                                                                                                                                                                     |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| success                   | Response was successfully served, either from Cloudflare cache or forwarded from the upstream.                                                                                                  |
| upstream\_failure         | Response could not be fetched from the upstream due to the upstream failing to respond.                                                                                                         |
| upstream\_servfail        | Response could not be fetched from the upstream due to the upstream responding with SERVFAIL.                                                                                                   |
| invalid\_query            | Query is invalid and cannot be processed.                                                                                                                                                       |
| any\_type\_blocked        | Query of type ANY was blocked according to your [DNS Firewall settings](https://developers.cloudflare.com/dns/dns-firewall/setup/) ([RFC 8482 ↗](https://www.rfc-editor.org/rfc/rfc8482.html)). |
| rate\_limit               | Query was rate limited according to your [DNS Firewall settings](https://developers.cloudflare.com/dns/dns-firewall/setup/).                                                                    |
| chaos\_success            | Response for [Chaos class ↗](https://en.wikipedia.org/wiki/Chaosnet) was successfully served.                                                                                                   |
| attack\_mitigation\_block | Query was blocked as part of [random prefix attack mitigation](https://developers.cloudflare.com/dns/dns-firewall/random-prefix-attacks/).                                                      |
| unknown                   | There was an unknown error.                                                                                                                                                                     |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/dns-firewall/","name":"DNS Firewall"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/dns-firewall/analytics/","name":"Analytics and logs"}}]}
```

---

---
title: DNS Firewall FAQ
description: Find answers to common questions about Cloudflare's DNS Firewall, including cache behavior, EDNS support, and setting PTR records.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNS Firewall FAQ

Consider the answers for frequently asked questions about Cloudflare DNS Firewall.

## How does DNS Firewall choose a backend nameserver to query upstream?

DNS Firewall alternates between a customer's nameservers, using an algorithm that is more likely to send queries to the faster upstream nameservers than slower nameservers.

## How long does DNS Firewall cache a stale object?

DNS Firewall sets cache longevity according to allocated memory.

As long as there is enough allocated memory, Cloudflare does not clear items from the cache forcefully, even when the TTL expires. This feature allows Cloudflare to serve stale objects from cache if your nameservers are offline.

## Does the DNS Firewall cache SERVFAIL?

Yes. `SERVFAIL` is treated like any other negative answer for caching purposes. The default TTL is 30 seconds. You can use the [API](https://developers.cloudflare.com/api/resources/dns%5Ffirewall/methods/edit/) to set a different `negative_cache_ttl`.

## Does DNS Firewall support EDNS Client Subnet (ECS)?

Yes. Often, DNS providers want to see a client's IP via EDNS Client Subnet (ECS) ([RFC 7871 ↗](https://www.rfc-editor.org/rfc/rfc7871.html)) because they serve geographically specific DNS answers based on the client's IP. With EDNS Client Subnet enabled, the DNS Firewall will forward the client's IP subnet along with the DNS query to the upstream nameserver.

When EDNS is enabled, the DNS Firewall gives out the geographically correct answer in cache based on the client IP subnet. To do this, the DNS Firewall segments its cache. For example:

1. A resolver says it is looking for an answer for client `192.0.2.0/24`.
2. The DNS Firewall will proxy the request to the upstream nameserver for the answer.
3. The DNS Firewall will cache the answer from the upstream nameserver, but only for that `/24`.
4. `203.0.113.0/24` now asks the same DNS question and the answer is again returned from the upstream nameserver instead of the cache.

Note

EDNS limits the effectiveness of the DNS cache.

Some resolvers might not be sending any EDNS data. When you set the `ecs_fallback` parameter to `true` via the [API](https://developers.cloudflare.com/api/resources/dns%5Ffirewall/methods/edit/), DNS Firewall will forward the IP subnet of the resolver instead only if there is no EDNS data present in incoming the DNS query.

## Does DNS Firewall cache negative answers?

Yes. The default TTL is 30 seconds. You can set `negative_cache_ttl` via the [API](https://developers.cloudflare.com/api/resources/dns%5Ffirewall/methods/edit/). This will affect the TTL of responses with status `REFUSED`, `NXDOMAIN`, or `SERVFAIL`.

## How can I set PTR records for nameserver hostnames?

To set up PTR records for the DNS Firewall cluster IPs that point to your nameserver hostnames, use the following API endpoints:

* [Show DNS Firewall Cluster Reverse DNS](https://developers.cloudflare.com/api/resources/dns%5Ffirewall/subresources/reverse%5Fdns/methods/get/)
* [Update DNS Firewall Cluster Reverse DNS](https://developers.cloudflare.com/api/resources/dns%5Ffirewall/subresources/reverse%5Fdns/methods/edit/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/dns-firewall/","name":"DNS Firewall"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/dns-firewall/faq/","name":"DNS Firewall FAQ"}}]}
```

---

---
title: Random prefix attack mitigation
description: Block random prefix DNS queries that target your upstream authoritative nameservers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Random prefix attack mitigation

Random prefix attacks are when someone sends a lot of traffic to subdomains that are highly unlikely to exist (`12345.example.com`, `abcdefg.example.com`), but are still associated with your main domain (`example.com`).

Usually, a DNS query to each random subdomain (or prefix) is not repeated, so it cannot be cached by resolvers or any other proxies and always reaches the authoritative nameservers. Rate limiting or blocking queries based on source IP can introduce a high amount of false positives, since random prefix attacks commonly are conducted via public resolvers. This makes these attacks particularly effective and hard to mitigate.

As part of [DNS Firewall](https://developers.cloudflare.com/dns/dns-firewall/), Cloudflare can protect your upstream authoritative nameservers from these attacks by blocking DNS queries that are determined to be part of an attack and thus preventing them from reaching your authoritative nameservers, where they could cause harm by overloading resources. This protection is an opt-in feature because of the potential for false positives.

## Resources

* [Background information](https://developers.cloudflare.com/dns/dns-firewall/random-prefix-attacks/about/)
* [Setup](https://developers.cloudflare.com/dns/dns-firewall/random-prefix-attacks/setup/)

## Limitations

To reduce the impact of false positives, Cloudflare does not block entire [public suffixes ↗](https://publicsuffix.org/) (such as `com`). However, it can block domains directly under them (such as `example.com`).

In addition, the default setting for the automatic mitigation ensures that it will only be deployed if upstream authoritative nameservers are determined to be unresponsive (and likely overloaded by an attack). This means that, as long as your authoritative nameservers can handle the traffic during a random prefix attack, Cloudflare will not actively block queries in order to avoid false positives. This setting is called `"only_when_upstream_unhealthy"` and is always true if not explicitly disabled during [Setup](https://developers.cloudflare.com/dns/dns-firewall/random-prefix-attacks/setup/).

Because Cloudflare does not know which domains and subdomains exist as DNS records on an upstream nameserver, this feature takes a best effort approach by blocking DNS queries to affected subdomains in order to allow upstream nameservers to keep responding to DNS queries to unaffected subdomains.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/dns-firewall/","name":"DNS Firewall"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/dns-firewall/random-prefix-attacks/","name":"Random prefix attack mitigation"}}]}
```

---

---
title: About
description: Learn about random prefix attacks. As part of DNS Firewall, Cloudflare can protect your upstream authoritative nameservers from these attacks.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# About

Random prefix attacks are when someone sends a lot of traffic to subdomains that are highly unlikely to exist (`12345.example.com`, `abcdefg.example.com`), but are still associated with your main domain (`example.com`).

Usually, a DNS query to each random subdomain (or prefix) is not repeated, so it cannot be cached by resolvers or any other proxies and always reaches the authoritative nameservers. Rate limiting or blocking queries based on source IP can introduce a high amount of false positives, since random prefix attacks commonly are conducted via public resolvers. This makes these attacks particularly effective and hard to mitigate.

  
## Attack characteristics

### Queries for nonexistent domains

If the request only involved nonexistent domains, the `NXDOMAIN` errors would only be served by the top-level domain (TLD) nameservers for `com.`. This means that the queries never reach the authoritative nameservers.

    flowchart TD
      accTitle: Random prefix attacks diagram
      A[End user query to <code>example.com</code>] --"1)"--> B[<code>1.1.1.1 resolver</code>]
      B --"2)"--> C[<code>com.</code> TLD NS]
      C --"3)" <code>NXDOMAIN error</code>--> B
      B --"4)" <code>NXDOMAIN error</code>--> A
      D[Authoritative NS]

  
### Queries for nonexistent subdomains

These attacks are successful because they target subdomains, which require a response from a domain's authoritative nameservers.

    flowchart TD
      accTitle: Random prefix attacks diagram
      A[End user query to <code>random.example.com</code>] --"1)"--> B[<code>1.1.1.1 resolver</code>]
      B -- "2)" --> C[<code>com.</code> TLD NS]
      C -- "3)" Query Authoritative NS --> B
      B -- "4)" --> D[Authoritative NS]
      D --"5)" <code>NXDOMAIN error</code>--> B
      B --"6)" <code>NXDOMAIN error</code>--> A

  
With an attack against a subdomain of an existing domain, the resolver is forced to fully resolve it against the authoritative nameservers since these random subdomains are likely not cached by the resolver or any other proxy. If an attacker sends enough of these queries, and the authoritative nameservers cannot handle the query load, it will become unresponsive or even fall over, taking all zones it is hosting down, not just the attacked zone.

This attack is difficult to mitigate for a few reasons. From the perspective of the authoritative nameservers, the attacker appears to be Cloudflare (`1.1.1.1`) since that is the source of the queries. Blocking Cloudflare is not an option since that will block legitimate traffic.

## Solution

When you [enable random prefix attack mitigations](https://developers.cloudflare.com/dns/dns-firewall/random-prefix-attacks/setup/), Cloudflare monitors incoming queries for potential random prefix attacks.

When we detect an attack, we will temporarily stop querying your upstream nameservers for subdomains, sub-subdomains, and more. Cloudflare will then respond with cached responses (if their TTL has not yet expired).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/dns-firewall/","name":"DNS Firewall"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/dns-firewall/random-prefix-attacks/","name":"Random prefix attack mitigation"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/dns-firewall/random-prefix-attacks/about/","name":"About"}}]}
```

---

---
title: Setup
description: Enable automatic mitigation of random prefix attacks via the API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Setup

In order to enable automatic mitigation of [random prefix attacks](https://developers.cloudflare.com/dns/dns-firewall/random-prefix-attacks/about/):

1. Set up [DNS Firewall](https://developers.cloudflare.com/dns/dns-firewall/setup/).
2. Send a [PATCH request](https://developers.cloudflare.com/api/resources/dns%5Ffirewall/methods/edit/) to update your DNS Firewall cluster.  
Required API token permissions  
At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:  
   * `DNS Firewall Write`  
Update DNS Firewall Cluster  
```  
curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/dns_firewall/$DNS_FIREWALL_ID" \  
  --request PATCH \  
  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \  
  --json '{  
    "attack_mitigation": {  
        "enabled": true,  
        "only_when_upstream_unhealthy": true  
    }  
  }'  
```

Once you receive a `200` success response from the API, queries identified as being part of a random prefix attack will receive a `REFUSED` response.

Note

If you do not specify otherwise in your API call, Cloudflare automatically sets the `"only_when_upstream_unhealthy"` parameter to true, which means that Cloudflare will only mitigate attacks when we detect that the upstream is unresponsive (possibly as a result of an attack). This setting can also be changed via the API, using a request similar to the ones shown above.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/dns-firewall/","name":"DNS Firewall"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/dns-firewall/random-prefix-attacks/","name":"Random prefix attack mitigation"}},{"@type":"ListItem","position":5,"item":{"@id":"/dns/dns-firewall/random-prefix-attacks/setup/","name":"Setup"}}]}
```

---

---
title: Setup
description: Set up DNS Firewall to protect upstream nameservers from DDoS attacks and reduce load by caching DNS responses.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Setup

## Prerequisites

Prior to setting up DNS Firewall, you need:

* Account access to DNS Firewall (provided by your Enterprise account team).
* Access to **DNS Administrator** or **Super Administrator** privileges on your account.
* Newly updated IP addresses for your nameservers (protects against previously compromised IP addresses).

## Configure DNS Firewall

### Create a DNS Firewall cluster

* [ Dashboard ](#tab-panel-7923)
* [ API ](#tab-panel-7924)

1. In the Cloudflare dashboard, go to the **DNS Firewall Clusters** page.  
[ Go to **Clusters** ](https://dash.cloudflare.com/?to=/:account/dns-firewall/clusters)
2. Select **Add Firewall Cluster**.
3. Fill out the required fields, including:  
   * **IP Addresses**: The upstream IPv4 and/or IPv6 addresses of your authoritative nameservers.  
   * **Minimum Cache TTL**: Recommended setting of **30 seconds**.  
   * **Maximum Cache TTL**: Recommended setting of **4 hours**. Larger values increase the cache hit ratio, but also increase the time required for DNS changes to propagate.  
   * **ANY queries**: Recommended setting is **Off** because these are often used as part of DDoS attacks. Also refer to this [blog post ↗](https://blog.cloudflare.com/rfc8482-saying-goodbye-to-any/).
4. Click **Continue**.
5. On the following screen, save the values for **Your new DNS Firewall IP Addresses**.

Note:

If you forget to save your new IP addresses, find your cluster and click **IP Addresses**.

If you delete your cluster, the assigned set of IPs will be lost. If you recreate the cluster you will get a different set of IPs.

You can also create a DNS Firewall cluster by sending a [POST request](https://developers.cloudflare.com/api/resources/dns%5Ffirewall/methods/create/) to the API.

### Update registrar settings

Update the `A/AAAA` glue records for your nameserver hostnames at your registrar with your DNS Firewall cluster IP addresses.

### Update DNS servers

At your DNS servers, update the `A/AAAA` records for your nameserver hostnames in your DNS zone file with your DNS Firewall cluster IP addresses.

### Test DNS resolution

Confirm that your nameservers are functioning correctly by running a `dig` command.

### Update security policies

Configure security policy in your DNS servers and Firewall to allow only [Cloudflare IPs ↗](https://cloudflare.com/ips) and TCP/UDP port 53.

## Additional options

When you use the API, you can also specify other parameters, such as rate limit (in queries per second per data center). You can find the parameters descriptions and examples in the [API documentation](https://developers.cloudflare.com/api/resources/dns%5Ffirewall/methods/create/).

To configure rate limiting and other options for already existing clusters, use the [Update DNS Firewall Cluster](https://developers.cloudflare.com/api/resources/dns%5Ffirewall/methods/edit/) endpoint.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/dns-firewall/","name":"DNS Firewall"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/dns-firewall/setup/","name":"Setup"}}]}
```

---

---
title: Troubleshooting
description: Troubleshoot common Cloudflare DNS issues.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

The following topics are useful for troubleshooting DNS issues.

Filter resources...

[FAQs — DNS Firewall](https://developers.cloudflare.com/dns/dns-firewall/faq/)[Troubleshooting DNSSEC](https://developers.cloudflare.com/dns/dnssec/troubleshooting/)[FAQ](https://developers.cloudflare.com/dns/faq/)[Cannot verify a domain with CNAME](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/cname-domain-verification/)[Existing NS records block new record creation](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/existing-ns-record/)[Exposed IP addresses](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/exposed-ip-address/)[Cannot add DNS records with the same name](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/records-with-same-name/)[Stale response for upstream DNS resolution](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/stale-response/)[Unexpected DNS records](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/unexpected-dns-records/)[Troubleshooting](https://developers.cloudflare.com/dns/private-origins/troubleshooting/)[Enforce DNS-only](https://developers.cloudflare.com/dns/proxy-status/enforce-dns-only/)[Available debug endpoints](https://developers.cloudflare.com/dns/troubleshooting/dns-debug-endpoints/)[General DNS issues](https://developers.cloudflare.com/dns/troubleshooting/dns-issues/)[Fix DNS\_PROBE\_FINISHED\_NXDOMAIN](https://developers.cloudflare.com/dns/troubleshooting/dns-probe-finished-nxdomain/)[Fix DNS\_PROBE\_POSSIBLE error](https://developers.cloudflare.com/dns/troubleshooting/dns-probe-possible/)[Troubleshooting email issues](https://developers.cloudflare.com/dns/troubleshooting/email-issues/)[Troubleshooting primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/troubleshooting/)[Cannot add domain to Cloudflare](https://developers.cloudflare.com/dns/zone-setups/troubleshooting/cannot-add-domain/)[Delete all DNS records](https://developers.cloudflare.com/dns/zone-setups/troubleshooting/delete-all-records/)[Domain deleted from Cloudflare](https://developers.cloudflare.com/dns/zone-setups/troubleshooting/domain-deleted/)[Zone stuck in Pending Nameserver Update](https://developers.cloudflare.com/dns/zone-setups/troubleshooting/pending-nameservers/)[Troubleshooting secondary nameservers](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/troubleshooting/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: Available debug endpoints
description: Use dig commands against Cloudflare nameservers to find your public IP, connected data center, DNS software version, and more.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Available debug endpoints

The following debug endpoints are available via `dig` or other DNS query tools.

Note

For all commands, replace `alex.ns.cloudflare.com` with your Cloudflare-assigned nameservers.

## Get your public IP address

Terminal window

```

dig @alex.ns.cloudflare.com chaos txt myip.cloudflare +short


```

This command returns your public IP address, meaning the IP address that Cloudflare receives the DNS query from. This is useful for debugging when you need to know your own IP.

## Find your connected data center

Terminal window

```

dig @alex.ns.cloudflare.com chaos txt id.server +short


```

This command returns the Cloudflare data center you are connecting to, for DNS queries sent from where you execute this command.

## Check the DNS software version

Terminal window

```

dig @alex.ns.cloudflare.com chaos txt version.bind +short


```

This command returns the version of Cloudflare's authoritative DNS software that is running on the data center you are connected to. Usually, the same version is present on all Cloudflare data centers. However, since Cloudflare performs staged releases, different versions can exist on different data centers.

## Get your IP, ASN, and country code

Terminal window

```

dig @alex.ns.cloudflare.com txt whoami.cloudflare.net +short


```

This command returns your public IP (same as the first command), your ASN, and the associated country code, all indicating where you are sending the query from.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/troubleshooting/dns-debug-endpoints/","name":"Available debug endpoints"}}]}
```

---

---
title: General DNS issues
description: Troubleshoot common DNS resolution errors like &quot;This site can't be reached&quot;, err_name_not_resolved, and Error 1001 when using Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# General DNS issues

In web browsers such as Safari or Chrome, there are several commonly observable DNS errors:

* `This site can't be reached`
* `This webpage is not available`
* `err_name_not_resolved`
* `Can't find the server`
* [Error 1001 DNS resolution error](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-1xxx-errors/error-1001/)

## Common causes and resolutions

Below are the most common causes for DNS resolution errors along with suggested solutions.

### Mistyped domain or subdomain

Verify that the domain or subdomain was correctly spelled in the request URL.

### Missing DNS records

Ensure that you have the necessary DNS records for the domain or subdomain that is presenting the error.

[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) 

This includes having the following records:

* The [zone apex](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-zone-apex/) (e.g., `example.com`) record.
* Existing [subdomains](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-subdomain/) (`www.example.com`, `blog.example.com`) records.

Note

If you have a [CNAME setup (partial)](https://developers.cloudflare.com/dns/zone-setups/partial-setup), ensure your DNS records also exist in your authoritative nameservers.

### DNSSEC was not disabled before the domain was added to Cloudflare

DNS resolution failures occur if [DNSSEC is not disabled](https://developers.cloudflare.com/dns/dnssec/#disable-dnssec) at your domain provider before you add the domain to Cloudflare.

### Nameservers no longer point to Cloudflare

If you manage DNS records via the Cloudflare dashboard and your domain stops pointing to Cloudflare's nameservers, DNS resolution will stop functioning.

This can occur if your domain registrar switches the nameservers for your domain to point to their default nameservers. To confirm if this is the problem, [check whether your domain uses Cloudflare's nameservers](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/#35-verify-changes).

### Unresolved IP address

In rare cases, the DNS resolver in the client requesting the URL might fail to resolve a DNS record to a valid IP address.

Reload the page after a short wait to note if the problem disappears. This issue is unrelated to Cloudflare, but using [Cloudflare's DNS resolver](https://developers.cloudflare.com/1.1.1.1/setup/) may help. Contact your hosting provider for additional help with your current DNS resolver.

### Newly created record still does not resolve

If you recently created a DNS record and resolvers still return `NXDOMAIN` (Non-Existent Domain) or no answer, it is likely because a negative response is currently stored in the resolver's cache.

When a resolver is queried for a hostname that has no DNS records yet, it caches the empty response so it does not have to ask the authoritative nameserver again immediately. This is known as negative caching.

For newly created records:

* The resolver might not have cached the new record yet. Instead, it is using a prior `NXDOMAIN` cache entry that says "this record does not exist," which was generated if the hostname was queried before you created the record.
* The duration of this negative cache is determined by the `MINIMUM` field in your zone's SOA record (per [RFC 2308 ↗](https://datatracker.ietf.org/doc/html/rfc2308)), not the TTL of the record you just created. Different resolvers may cache for varying durations.

This means:

* Lowering the TTL on your new record will not speed up resolution if a negative cache entry already exists; the resolver will only see your new TTL after the old negative entry expires.
* Flushing your local DNS cache only affects your specific device; the upstream recursive resolver (for example, your ISP or a public provider) still holds the negative result.
* Propagation appears uneven because different resolvers may have queried the name at different times, apply different negative cache TTLs, or have no negative cache entry at all.

The exact behavior differs per resolver, but to estimate how long you need to wait, query your zone's SOA record and look at the last value (the `MINIMUM` field). You must wait for that interval to pass since the last `NXDOMAIN` query before the new record will consistently resolve.

You can check if a negative cache entry is active by querying for the non-existent (or newly created) hostname:

Terminal window

```

dig +noall +answer +authority mynewrecord.example.com


```

If the record is still negatively cached, the response will include the zone's SOA record in the authority section with a TTL indicating how many seconds remain before the entry expires:

```

example.com.    256  IN  SOA  ...


```

In this example, the negative cache response will continue for 256 more seconds.

To verify the record resolves correctly, you can purge the cache for public resolvers and query the record. If this works, other resolvers will eventually start resolving as well:

* [Purge 1.1.1.1 cache ↗](https://one.one.one.one/purge-cache/)
* [Purge 8.8.8.8 cache ↗](https://dns.google/cache)
* [Query 8.8.8.8 ↗](https://dns.google/)
* [Query and refresh OpenDNS cache ↗](https://cachecheck.opendns.com/)

#### Further debugging

To verify the record was correctly created, query Cloudflare's authoritative nameservers directly:

Terminal window

```

# Find the authoritative nameservers for your zone

dig @1.1.1.1 example.com NS +short


```

Terminal window

```

# Query the authoritative nameserver for your new record

dig @hera.ns.cloudflare.com mynewrecord.example.com A


```

Querying the authoritative nameserver directly bypasses resolver caching. If the record is returned, resolvers will eventually start returning it as well. If the record does not appear, verify the record exists in the Cloudflare dashboard and that the hostname matches exactly.

### Account recovery

If you are locked out of the Cloudflare account that contains your DNS configuration, refer to [Account recovery](https://developers.cloudflare.com/fundamentals/user-profiles/account-recovery/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/troubleshooting/dns-issues/","name":"General DNS issues"}}]}
```

---

---
title: DNS_PROBE_FINISHED_NXDOMAIN
description: Learn how to fix the DNS_PROBE_FINISHED_NXDOMAIN browser error, which indicates the domain does not exist.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNS\_PROBE\_FINISHED\_NXDOMAIN

If you or your visitors experience `DNS_PROBE_FINISHED_NXDOMAIN` errors after you [activate your domain on Cloudflare](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/), review your DNS records in Cloudflare.

Note

If your domain is added to Cloudflare by a hosting partner, manage your DNS records via the hosting partner.

## Background

`DNS_PROBE_FINISHED_NXDOMAIN` indicates that the DNS lookup completed and the result was that the domain does not exist. `DNS_PROBE_FINISHED` means that the DNS probe ran to completion and `NXDOMAIN` stands for non-existent domain. Together, these messages mean that the DNS resolver determined the requested domain has no associated [DNS records](https://developers.cloudflare.com/dns/manage-dns-records/).

Though visitors sometimes encounter this error — or similarly worded messages from Safari, Edge, or Firefox — because of network or local DNS issues, it might point to an issue with your DNS records in Cloudflare.

## Potential solutions

If you experience `DNS_PROBE_FINISHED_NXDOMAIN` errors with a newly activated domain, review your DNS settings in the Cloudflare dashboard.

Check your expected apex domain (`example.com`) and any active subdomains (`www.example.com` or `blog.example.com`). If they do not resolve correctly, you may need to [add a record on the zone apex](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-zone-apex/) or a [subdomain record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-subdomain/) in Cloudflare DNS.

If you have the correct records set up, make sure those records are also pointing to the correct origin IP address.

After making changes to your DNS records, you may need to wait a few minutes for those changes to take effect.

Note

For additional troubleshooting help, refer to the [Community troubleshooting guide ↗](https://community.cloudflare.com/t/community-tip-fixing-the-dns-probe-finished-nxdomain-error/42818).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/troubleshooting/dns-probe-finished-nxdomain/","name":"DNS_PROBE_FINISHED_NXDOMAIN"}}]}
```

---

---
title: DNS_PROBE_POSSIBLE
description: Learn how to fix the DNS_PROBE_POSSIBLE browser error when using Cloudflare DNS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNS\_PROBE\_POSSIBLE

If you or your visitors experience `DNS_PROBE_POSSIBLE` errors after you [activate your domain on Cloudflare](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/), review your DNS records in Cloudflare.

Note

If your domain is added to Cloudflare by a hosting partner, manage your DNS records via the hosting partner.

## Background

`DNS_PROBE_POSSIBLE` means that the resolver could not find [DNS records](https://developers.cloudflare.com/dns/manage-dns-records/) for the requested hostname.

Though visitors sometimes encounter this error — or similarly worded messages from Safari, Edge, or Firefox — because of network or local DNS issues, it might point to an issue with your DNS records in Cloudflare.

## Potential solutions

If you experience `DNS_PROBE_POSSIBLE` errors with a newly activated domain, review your DNS settings in the Cloudflare dashboard.

Check your expected apex domain (`example.com`) and any active subdomains (`www.example.com` or `blog.example.com`). If they do not resolve correctly, you may need to [add a record on the zone apex](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-zone-apex/) or a [subdomain record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-subdomain/) in Cloudflare DNS.

If you have the correct records set up, make sure those records are also pointing to the correct origin IP address.

After making changes to your DNS records, you may need to wait a few minutes for those changes to take effect.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/troubleshooting/dns-probe-possible/","name":"DNS_PROBE_POSSIBLE"}}]}
```

---

---
title: Email issues
description: Resolve email delivery issues related to DNS configuration.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Email issues

If you have issues sending or receiving mail, follow these troubleshooting steps.

## Are your records correct?

To check that your MX records are resolving correctly, run the following `dig` command in your terminal (replace `example.com` with your domain):

Terminal window

```

dig example.com mx +short


```

Alternatively, you can use a third-party tool to look up your MX records. For a list of options, refer to [Recommended third-party tools](https://developers.cloudflare.com/dns/reference/recommended-third-party-tools/).

This returns a list of mail servers for your domain. Compare the output to the MX records on your Cloudflare DNS records page.

[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) 

If the mail server listed does not match your email provider's expected value, update the MX record content to the correct value. Check your email provider's setup documentation for the correct MX record values.

If your DNS query returns records you do not recognize, such as `_dc-mx` or `dc-#####` subdomains, refer to [Unexpected DNS records](https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/unexpected-dns-records/#%5Fdc-mx-and-dc--subdomains).

## Are DNS records missing?

If `dig` returns no results for your domain's MX records, your records may not have been created or may have been accidentally deleted.

Even if your MX records are correct, missing email authentication records can cause delivery failures:

* **Missing `SPF` record:** receiving servers cannot verify that your domain authorizes the sending server, which may cause messages to be rejected or marked as spam.
* **Missing `DKIM` record:** messages cannot be cryptographically verified as originating from your domain, which reduces trust with receiving servers.
* **Missing `DMARC` record:** receiving servers have no policy for handling messages that fail `SPF` or `DKIM` checks, which can lead to inconsistent delivery or spoofing of your domain.

Refer to [Set up email records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/email-records/) to add missing records.

## Do your MX records point to a delegated subdomain?

`NS` records [delegate a subdomain](https://developers.cloudflare.com/dns/manage-dns-records/how-to/subdomains-outside-cloudflare/#delegate-a-subdomain-outgoing) to another DNS provider. If your MX record points to a subdomain that is delegated via `NS` records (for example, `mail.example.com`), the mail server records are managed by that external provider, not Cloudflare. Confirm that the external provider has the correct `A` or `AAAA` records for the mail subdomain.

## Is CNAME flattening turned on?

Some email providers require `CNAME` records for features like DKIM authentication or autodiscover. When [CNAME flattening](https://developers.cloudflare.com/dns/cname-flattening/) is turned on — either globally for all `CNAME` records or individually on a specific record — the `CNAME` is flattened to an `A` record, which can prevent email providers from reading the record correctly.

If your email provider requires `CNAME` records and those records are not resolving as expected, you may need to turn off [CNAME flattening](https://developers.cloudflare.com/dns/cname-flattening/set-up-cname-flattening/).

## Is your mail hostname proxied?

Mail protocols such as SMTP, IMAP, and POP3 do not work through Cloudflare's standard HTTP proxy.

If the hostname used for mail resolves to a Cloudflare IP address, the record is proxied and mail clients will not be able to connect correctly.

Common examples include:

* `mail.example.com` used for SMTP, IMAP, or POP3
* Any hostname targeted by your `MX` record
* Autodiscover or mail service hostnames that must return the provider's actual DNS target

To fix this issue:

1. Go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. Locate the mail-related hostname.
3. Change the [proxy status](https://developers.cloudflare.com/dns/proxy-status/) to **DNS only**.

Your `MX` record itself is always DNS-only, but the hostname it points to must also resolve to a DNS-only target.

## Common provider record values

If you are not sure whether the DNS content itself is correct, compare it with the values from your provider.

Common examples include:

| Provider         | MX records                                                                                                                                                           | SPF record                                     |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
| Google Workspace | ASPMX.L.GOOGLE.COM (priority 1), ALT1.ASPMX.L.GOOGLE.COM and ALT2.ASPMX.L.GOOGLE.COM (priority 5), ALT3.ASPMX.L.GOOGLE.COM and ALT4.ASPMX.L.GOOGLE.COM (priority 10) | v=spf1 include:\_spf.google.com \~all          |
| Microsoft 365    | <your-domain>.mail.protection.outlook.com (priority 0)                                                                                                               | v=spf1 include:spf.protection.outlook.com -all |
| iCloud Mail      | mx01.mail.icloud.com and mx02.mail.icloud.com (priority 10)                                                                                                          | v=spf1 include:icloud.com \~all                |
| Mailgun          | mxa.mailgun.org and mxb.mailgun.org (priority 10)                                                                                                                    | v=spf1 include:mailgun.org \~all               |

Always confirm the exact values with your provider before making changes.

## Is Cloudflare Spectrum turned on?

Cloudflare does not proxy email traffic (SMTP, port 25) by default. Unless you have explicitly configured [Cloudflare Spectrum](https://developers.cloudflare.com/spectrum/reference/configuration-options#smtp) to proxy SMTP traffic, email is delivered directly to your mail server and does not pass through the Cloudflare network. DNS records used for email should be set to [DNS only](https://developers.cloudflare.com/dns/proxy-status/) to ensure mail traffic is not affected by the proxy.

[ Go to **Spectrum** ](https://dash.cloudflare.com/?to=/:account/:zone/spectrum) 

## Is Email Routing turned on?

If [Email Routing](https://developers.cloudflare.com/email-service/) is turned on, Cloudflare manages your MX records and may create additional DNS records automatically.

[ Go to **Email Routing** ](https://dash.cloudflare.com/?to=/:account/:zone/email/routing) 

If Email Routing is turned on but you use a different mail provider, the Email Routing MX records may conflict with your provider's records. You can [turn off Email Routing](https://developers.cloudflare.com/email-service/configuration/domains/#remove-a-domain-from-email-routing) to remove the managed records and configure your own.

---

## Best practices for MX records on Cloudflare

If possible, do not host a mail service on the same server as the web resource you want to protect, since emails sent to non-existent addresses get bounced back to the attacker and reveal the mail server IP address.

Cloudflare recommends using non-contiguous IPs from different IP ranges.

---

## Contact your mail provider for assistance

If your email does not work shortly after editing DNS records, contact your mail administrator or mail provider with the specific error or bounce message you are receiving. They can confirm whether the issue is with DNS resolution, mail server configuration, or message delivery.

If your provider confirms the issue is related to Cloudflare, [contact Cloudflare support](https://developers.cloudflare.com/support/contacting-cloudflare-support/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/troubleshooting/email-issues/","name":"Email issues"}}]}
```

---

---
title: FAQ
description: Find answers to common questions about Cloudflare's authoritative DNS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# FAQ

The sections below cover frequently asked questions about Cloudflare authoritative DNS. For DNS Firewall, refer to [DNS Firewall FAQ](https://developers.cloudflare.com/dns/dns-firewall/faq/).

---

## Cloudflare offerings

### Is Cloudflare a free DNS (domain nameserver) provider?

Yes. Cloudflare offers [free DNS services ↗](https://www.cloudflare.com/dns) to customers on all plans. Note that:

* You do not need to change your hosting provider to use Cloudflare.
* You do not need to move away from your registrar. The only change you make with your registrar is to point the authoritative nameservers to the Cloudflare nameservers.

### Does Cloudflare charge for or limit DNS queries?

Cloudflare never limits or caps DNS queries, but the pricing depends on your plan level.

For customers on Free, Pro, or Business plans, Cloudflare does not charge for DNS queries. For customers on Enterprise plans, Cloudflare uses the number of monthly DNS queries as a pricing input to generate a custom quote.

### Does Cloudflare offer domain masking?

No. Cloudflare does not offer domain masking or DNS redirect services (your hosting provider might). However, we do offer URL forwarding through [Bulk Redirects](https://developers.cloudflare.com/rules/url-forwarding/bulk-redirects/).

### Can subdomains be added directly to Cloudflare?

Yes. Enterprise customers can add subdomains directly to Cloudflare via [subdomain support](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/).

### Does Cloudflare support EDNS0 (extension mechanisms for DNS)?

Yes, EDNS0 is a building block for modern DNS implementations and is enabled for all Cloudflare customers. EDNS0 adds support for signaling if the DNS Resolver (recursive DNS provider) supports larger message sizes and DNSSEC.

EDNS0 is the first approved set of mechanisms for [DNS extensions ↗](http://en.wikipedia.org/wiki/Extension%5Fmechanisms%5Ffor%5FDNS), originally published as [RFC 2671 ↗](https://www.rfc-editor.org/rfc/rfc2671.html).

---

## Nameservers

### Where can I find my Cloudflare nameservers?

On the **DNS Records** page, locate the **Cloudflare Nameservers** card.

[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) 

Also, the IP address associated with a specific Cloudflare nameserver can be retrieved via a dig command or a third-party DNS lookup tool hosted online such as [whatsmydns.net ↗](https://www.whatsmydns.net/):

Terminal window

```

dig kate.ns.cloudflare.com


```

```

kate.ns.cloudflare.com.    68675    IN    A    173.245.58.124.


```

### Where do I change my nameservers to point to Cloudflare?

Make the change at your registrar, which is where you registered your domain. This may or may not be your hosting provider - refer to [Update nameservers](https://developers.cloudflare.com/dns/nameservers/update-nameservers/) for further context.

If you do not know who your registrar is for the domain, a WHOIS search can help. You can use [ICANN Lookup ↗](https://lookup.icann.org/), for example.

Warning

Some country code TLDs may not be supported by ICANN Lookup. If that is the case, use a different WHOIS search tool.

Once you identify your registrar, follow their instructions.

Provider-specific instructions

This is not an exhaustive list of provider-specific instructions, but the following links may be helpful:

* [Ionos ↗](https://www.ionos.com/help/domains/using-your-own-name-servers/using-your-own-name-servers-for-a-domain/)
* [101Domain ↗](https://help.101domain.com/kb/managing-name-server-records)
* [Amazon ↗](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-name-servers-glue-records.html#domain-name-servers-glue-records-adding-changing)
* [Blacknight ↗](https://help.blacknight.com/hc/articles/4413036322321-How-do-I-change-the-nameservers-for-my-domain)
* [BlueHost ↗](https://www.bluehost.com/help/article/custom-nameservers)
* [DirectNIC ↗](https://directnic.com/knowledge/article/33:how%2Bdo%2Bi%2Bmodify%2Bname%2Bservers%2Bfor%2Bmy%2Bdomain%2Bname%253F)
* [DNSMadeEasy ↗](http://www.dnsmadeeasy.com/support/faq/)
* [Domain.com ↗](https://www.domain.com/help/article/domain-management-how-to-update-nameservers)
* [Dotster ↗](https://www.dotster.com/help/article/domain-management-how-to-update-nameservers)
* [DreamHost ↗](https://help.dreamhost.com/hc/en-us/articles/360038897151)
* [EasyDNS ↗](https://kb.easydns.com/knowledge/settingchanging-nameservers/)
* [Enom ↗](https://help.enom.com/hc/en-us/articles/115000486451-Nameservers-NS)
* [Fast Domain ↗](https://www.fastdomain.com/hosting/help/transfer%5Fclient%5Fstart)
* [FlokiNET ↗](https://billing.flokinet.is/index.php?rp=/knowledgebase/57/Nameserver-and-DNS-records.html)
* [Gandi ↗](https://docs.gandi.net/en/domain%5Fnames/common%5Foperations/changing%5Fnameservers.html)
* [GoDaddy ↗](https://www.godaddy.com/help/change-nameservers-for-your-domain-names-664)
* [HostGator ↗](https://www.hostgator.com/help/article/changing-name-servers)
* [Hostico ↗](https://hostico.ro/docs/setarea-nameserverelor-din-contul-de-client-hostico/)
* [HostMonster ↗](https://my.hostmonster.com/cgi/help/222)
* [Hover ↗](https://support.hover.com/support/solutions/articles/201000064742-changing-your-domain-nameservers)
* [Internetdbs ↗](https://faq.internetbs.net/hc/en-gb/articles/4516921367837-How-to-update-Nameservers-for-a-domain)
* [iPage ↗](https://www.ipage.com/help/article/domain-management-how-to-update-nameservers)
* [MelbourneIT ↗](https://support.melbourneit.au/docs/how-do-i-manage-my-dns-on-cpanel)
* [Moniker ↗](https://support.moniker.com/hc/en-gb/articles/10101271418653-How-to-update-Nameservers-for-a-domain)
* [Name.com ↗](https://www.name.com/support/articles/205934457-registering-custom-nameservers)
* [Namecheap ↗](https://www.namecheap.com/support/knowledgebase/article.aspx/767/10/how-can-i-change-the-nameservers-for-my-domain)
* [Network Solutions ↗](https://www.networksolutions.com/manage-it/edit-nameservers.jsp)
* [OVH ↗](https://docs.ovh.com/gb/en/domains/web%5Fhosting%5Fgeneral%5Finformation%5Fabout%5Fdns%5Fservers/#step-2-edit-your-domains-dns-servers)
* [Porkbun ↗](https://kb.porkbun.com/article/22-how-to-change-your-nameservers)
* [Rackspace ↗](https://support.rackspace.com/how-to/rackspace-name-servers/)
* [Register ↗](https://www.register.com/knowledge)
* [Squarespace ↗](https://support.squarespace.com/hc/articles/4404183898125-Nameservers-and-DNSSEC-for-Squarespace-managed-domains#toc-open-the-domain-s-advanced-settings)
* [Site5 ↗](https://kb.site5.com/dns-2/custom-nameservers/)
* [Softlayer ↗](https://cloud.ibm.com/docs/dns?topic=dns-add-edit-or-delete-custom-name-servers-for-a-domain)
* [Yola ↗](https://helpcenter.yola.com/hc/articles/360012492660-Changing-your-name-servers)

### Why have I received an email: (mydomain) stopped using Cloudflare's nameservers?

For domains where Cloudflare hosts the DNS, Cloudflare continuously checks whether the domain uses Cloudflare's nameservers for DNS resolution. If Cloudflare's nameservers are not used, the [domain status](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/) is updated from **Active** to **Moved** and an email is sent to the customer.

This is important because, if a domain is in a **Moved** state for a [long enough period of time](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/), it will be deleted from Cloudflare.

To recover a deleted domain, [re-add it in Cloudflare](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) just like you would for a new domain.

Warning

Cloudflare support is unable to restore DNS or settings for deleted domains.

---

## DNS records

### Does Cloudflare limit the number of DNS records a domain can have?

Yes. All customers have a limit on the number of DNS records they can create.

* Free: 200
* Pro: 3,500
* Business: 3,500
* Enterprise: 3,500

Free zones created before 2024-09-01 00:00:00 UTC have an increased limit of 1,000.

For more DNS records

If you are an Enterprise customer and require more DNS records, contact your account team. Cloudflare can support millions of DNS records on a single zone.

DNS records that other Cloudflare services create on your behalf — for example, the `TXT` and `MX` records added by [Email Routing](https://developers.cloudflare.com/email-service/) — also count toward this limit. To avoid disrupting those services, they are enforced against your record limit with a small buffer, so a zone may occasionally hold slightly more records than its limit would otherwise allow.

To create new records yourself through the dashboard or API, your zone must still be within its record limit.

### How long does it take for a DNS change I made to push out?

By default, any changes or additions you make to your Cloudflare zone file will take effect globally within 5 minutes, usually much less.

Depending on the Time-to-Live (TTL) set on the previous [DNS record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/), old data may still remain cached until the TTL expires. Proxied records expire after 5 minutes ("Automatic"), but the TTL for unproxied records can be customized.

If changes to records with large TTLs are anticipated, it may make sense to reduce the TTL ahead of time so that the change takes effect as quickly as possible.

### Why can't I make ANY queries to Cloudflare DNS servers?

`ANY` queries are special and often misunderstood. They are usually used to get all record types available on a DNS name, but what they return is just any type in the cache of recursive resolvers. This can cause confusion when they are used for debugging.

Because of Cloudflare's many advanced DNS features like CNAME flattening, it can be complex and even impossible to give correct answers to `ANY` queries. For example, when DNS records dynamically come and go or are stored remotely, it can be taxing or even impossible to get all the results at the same time.

Refer to [Deprecating the DNS ANY meta-query type ↗](https://blog.cloudflare.com/deprecating-dns-any-meta-query-type/) for details. The decision to block `ANY` does not affect DNS Firewall customers.

### How do I add ANAME records on Cloudflare?

ANAME or ALIAS are DNS records used by specific DNS providers. If your previous provider was using ANAME or ALIAS, you can recreate these records on Cloudflare as CNAME records. Cloudflare's [CNAME flattening](https://developers.cloudflare.com/dns/cname-flattening/)[1](#user-content-fn-1) allows you to create CNAME records at your [zone apex](https://developers.cloudflare.com/dns/concepts/#zone-apex), removing the need for those other record types.

## Footnotes

1. A process in which Cloudflare returns an IP address instead of the target hostname that a CNAME record points to. [↩](#user-content-fnref-1)

### Why does my TXT record show a double quote in the middle of the value?

This is expected behavior. Per [RFC 4408 ↗](https://www.rfc-editor.org/rfc/rfc4408#section-3.1.3) and the DNS protocol specification ([RFC 1035 ↗](https://www.rfc-editor.org/rfc/rfc1035#section-3.3.14)), a single DNS TXT record is composed of one or more character strings, each with a maximum length of 255 characters. When the value you enter exceeds 255 characters, it must be split into multiple strings. Each string is enclosed in double quotes (`"`), so the resulting record may appear to have a quote in the middle — for example, `"first part" "second part"`.

This splitting is required by the DNS protocol and is performed by all DNS providers, even if some do not display it in their UI or API. For all major TXT record use cases (such as SPF, DKIM, and DMARC), the receiving application will concatenate the strings back together, so the behavior of the record is not affected.

### Why are Cloudflare's A or AAAA records / IP addresses for my domain's DNS responses appearing?

For DNS records proxied to Cloudflare, Cloudflare's IP addresses are returned in DNS queries instead of your original server IP address. This allows Cloudflare to optimize, cache, and protect all requests for your website.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/faq/","name":"FAQ"}}]}
```

---

---
title: Changelog
description: Track the latest updates and changes to Cloudflare DNS features.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Changelog

[ Subscribe to RSS ](https://developers.cloudflare.com/changelog/rss/dns.xml) 

## 2026-06-10

  
**Account-level DNS records quota**   

Cloudflare now enforces DNS records quotas at the account level for Enterprise accounts. Instead of a per-zone limit, these accounts have a quota on the total number of records across all of their zones, letting you distribute records across your zones however you like — regardless of each zone's plan. Public and internal zones are counted separately, each with a default quota of 1,000,000 records.

Accounts without an account-level quota are unaffected: existing per-zone quotas behave exactly as before.

For more details, refer to [DNS records quota](https://developers.cloudflare.com/dns/manage-dns-records/#dns-records-quota).

## 2026-05-20

  
**New DNS records UX is rolling out**   

Starting today, everyone can opt in to a refreshed DNS records page in the Cloudflare dashboard. Over the coming weeks, the new experience will become the default for Free plan users first, followed by paid plans.

![New DNS records UX](https://developers.cloudflare.com/_astro/new-dns-ux.Bfs_yXPa_VJoah.webp) 

#### What is new

* **Better table experience**: resizable and hideable columns, row pinning, advanced filters with logical operators (AND/OR), configurable pagination, and expanded input fields so long values are no longer cut off.
* **First-class mobile experience**: responsive layout with a touch-friendly, card-based UI and compact controls for small screens.
* **DNS quick reference**: bite-sized explainers for DNS, proxy status, and TTL, available directly in the product to help users configure records without leaving the page.
* **Modern frontend**: a refactor onto Cloudflare's new UI framework that improves performance and lays the foundation for future improvements.
![New DNS records UX](https://developers.cloudflare.com/_astro/new-dns-ux.DV6gCbme_2cImvu.webp) 

#### Rollout plan

Dates are subject to change based on feedback received during the rollout.

* **20 May - 05 June**: ramped rollout to Free, then Pro and Business plans.
* **08 June - 03 July**: ramped rollout to Enterprise plans.

#### Share your feedback

Once the new experience is turned on for your account, look for the feedback link at the top of the DNS records page in the Cloudflare dashboard and let us know what you think. Your input helps us prioritize the next round of improvements.

## 2026-04-28

  
**Account-level enforce DNS-only**   

You can now disable Cloudflare's reverse proxy across all zones in your account simultaneously using the new `enforce_dns_only` setting. When enabled, Cloudflare responds to DNS queries for all proxied records with your origin IP addresses instead of Cloudflare's anycast IPs. This account-level kill switch is designed for incident response scenarios where you need to quickly route traffic directly to your origin servers.

Warning

Enabling this setting exposes your origin IP addresses and removes all Cloudflare protections — including DDoS mitigation, WAF, caching, and all other proxy-based features — for every zone in your account. Use with extreme caution and only after proper [preparations](https://developers.cloudflare.com/dns/proxy-status/enforce-dns-only/#preparation).

#### Key characteristics

* **Account-level** — Affects all zones in the account simultaneously with a single API call.
* **Non-destructive** — Does not modify your DNS records. Disabling the setting restores normal proxy behavior.
* **API-only** — Available through the API only, not in the Cloudflare dashboard.

#### What's affected

**Included:** Standard proxied A, AAAA, and CNAME records, Load Balancing records, and records matching Worker routes.

**Excluded:** Spectrum applications, Cloudflare Tunnel CNAMEs, R2 custom domains, Web3 gateways, and Workers custom domains continue to operate normally.

#### Before you enable

* Verify your origin servers can handle direct traffic without Cloudflare's caching and filtering.
* Review which origin IPs will become publicly visible through DNS queries.
* Test the API in a staging account before relying on it for incident response.

#### Availability

Available via API to all Cloudflare customers.

For information on how to use it, refer to [Enforce DNS-only developer documentation](https://developers.cloudflare.com/dns/proxy-status/enforce-dns-only/) .

## 2026-03-31

  
**Internal DNS - now in open beta**   

Internal DNS is now in open beta.

#### Who can use it?

Internal DNS is bundled as a part of Cloudflare Gateway and is now available to every Enterprise customer with one of the following subscriptions:

* Cloudflare Zero Trust Enterprise
* Cloudflare Gateway Enterprise

To learn more and get started, refer to the [Internal DNS documentation](https://developers.cloudflare.com/dns/internal-dns/).

## 2026-03-20

  
**DNS Analytics for Customer Metadata Boundary set to EU region**   

DNS Analytics is now available for customers with [Customer Metadata Boundary](https://developers.cloudflare.com/data-localization/metadata-boundary/) (CMB) set to EU. Query your DNS analytics data while keeping metadata stored in the EU region.

This update includes:

* **DNS Analytics** — Access the same DNS analytics experience for zones in CMB=EU accounts.
* **EU data residency** — Analytics data is stored and queried from the EU region, meeting data localization requirements.
* **DNS Firewall Analytics** — DNS Firewall analytics is now supported for CMB=EU customers.

#### Availability

Available to customers with the [Data Localization Suite](https://developers.cloudflare.com/data-localization/) who have Customer Metadata Boundary configured for the EU region.

#### Where to find it

* **Authoritative DNS:** In the Cloudflare dashboard, select your zone and go to the **Analytics** page.  
[ Go to **Analytics** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/analytics)
* **DNS Firewall:** In the Cloudflare dashboard, go to the **DNS Firewall Analytics** page.  
[ Go to **Analytics** ](https://dash.cloudflare.com/?to=/:account/dns-firewall/analytics)

For more information, refer to [DNS Analytics](https://developers.cloudflare.com/dns/additional-options/analytics/) and [DNS Firewall Analytics](https://developers.cloudflare.com/dns/dns-firewall/analytics/).

## 2025-09-16

  
**DNS Firewall Analytics — now in the Cloudflare dashboard**   

#### What's New

Access [GraphQL-powered DNS Firewall analytics](https://developers.cloudflare.com/dns/dns-firewall/analytics/) directly in the Cloudflare dashboard.

![DNS Firewall Analytics UI](https://developers.cloudflare.com/_astro/DNSFW_Analytics_UI.CgjmZFOO_Z1tNsEz.webp) 

#### Explore Four Interactive Panels

* **Query summary**: Describes trends over time, segmented by dimensions.
* **Query statistics**: Describes totals, cached/uncached queries, and processing/response times.
* **DNS queries by data center**: Describes global view and the top 10 data centers.
* **Top query statistics**: Shows a breakdown by key dimensions, with search and expand options (up to top 100 items).

Additional features:

* Apply filters and time ranges once. Changes reflect across all panels.
* Filter by dimensions like query name, query type, cluster, data center, protocol (UDP/TCP), IP version, response code/reason, and more.
* Access up to 62 days of historical data with flexible intervals.

#### Availability

Available to all DNS Firewall customers as part of their existing subscription.

#### Where to Find It

* In the Cloudflare dashboard, go to the **DNS Firewall** page.  
[ Go to **Analytics** ](https://dash.cloudflare.com/?to=/:account/dns-firewall/analytics)
* Refer to the [DNS Firewall Analytics](https://developers.cloudflare.com/dns/dns-firewall/analytics/) to learn more.

## 2025-06-19

  
**Account-level DNS analytics now available via GraphQL Analytics API**   

Authoritative DNS analytics are now available on the **account level** via the [Cloudflare GraphQL Analytics API](https://developers.cloudflare.com/analytics/graphql-api/).

This allows users to query DNS analytics across multiple zones in their account, by using the `accounts` filter.

Here is an example to retrieve the most recent DNS queries across all zones in your account that resulted in an `NXDOMAIN` response over a given time frame. Please replace `a30f822fcd7c401984bf85d8f2a5111c` with your actual account ID.

GraphQL example for account-level DNS analytics

```

query GetLatestNXDOMAINResponses {

  viewer {

    accounts(filter: { accountTag: "a30f822fcd7c401984bf85d8f2a5111c" }) {

      dnsAnalyticsAdaptive(

        filter: {

          date_geq: "2025-06-16"

          date_leq: "2025-06-18"

          responseCode: "NXDOMAIN"

        }

        limit: 10000

        orderBy: [datetime_DESC]

      ) {

        zoneTag

        queryName

        responseCode

        queryType

        datetime

      }

    }

  }

}


```

[Run in GraphQL API Explorer](https://graphql.cloudflare.com/explorer?query=I4VwpgTgngBA4mALgGQIaLAZ0QOQBoAiA8gLICCAkjgEpYAOA9gHaZYwDeAUDDAG4CWYAO6QO3HjFQBjKQxBNEmABQAzfgBsMEAFwdJMuQoAqqAOa6ARKgDMABhUAOAExOVUgCYB2KQBZbARgBOBx8AI0cAVncHFSdUCP9EqQsYAF8ASjEJCXcWMiZUdShEfilMMndUOhLeMCVxbJ41TUhdLkbGyowAfVMwYEsnWycIgFpbADZR-wmLBo6YLrBu9X7B4bHJ6Yc5hYkIemZWAGEGdzBLfGJyKl2F1Pns9X4AW35EXX9bb9tHiQYIOcIAAhKC6ADaSxKL2WBAAogBlY4AXT+mXaCwAXswwCZTH8eKBIFAcKgYQSYAdMIwWGBTucKUToEYoHQwBSoa92R0HtleWlOKkgA&variables=N4XyA)

To learn more and get started, refer to the [DNS Analytics documentation](https://developers.cloudflare.com/dns/additional-options/analytics/#analytics).

## 2025-06-16

  
**Internal DNS (beta) now manageable in the Cloudflare dashboard**   

Participating beta testers can now fully configure [Internal DNS](https://developers.cloudflare.com/dns/internal-dns/) directly in the [Cloudflare dashboard ↗](https://dash.cloudflare.com/?to=/:account/internal-dns).

#### Internal DNS enables customers to:

* Map internal hostnames to private IPs for services, devices, and applications not exposed to the public Internet
* Resolve internal DNS queries securely through [Cloudflare Gateway](https://developers.cloudflare.com/cloudflare-one/traffic-policies/)
* Use split-horizon DNS to return different responses based on network context
* Consolidate internal and public DNS zones within a single management platform

#### What’s new in this release:

* Beta participants can now create and manage internal zones and views in the Cloudflare dashboard
![Internal DNS UI](https://developers.cloudflare.com/_astro/internal-dns-beta-ui.B5uCVZ9o_yVcqC.webp) 

Note

The Internal DNS beta is currently only available to Enterprise customers.

To learn more and get started, refer to the [Internal DNS documentation](https://developers.cloudflare.com/dns/internal-dns/).

## 2025-06-11

  
**NSEC3 support for DNSSEC**   

Enterprise customers can now select NSEC3 as method for proof of non-existence on their zones.

What's new:

* **NSEC3 support for live-signed zones** – For both primary and secondary zones that are configured to be live-signed (also known as "on-the-fly signing"), NSEC3 can now be selected as proof of non-existence.
* **NSEC3 support for pre-signed zones** – Secondary zones that are transferred to Cloudflare in a [pre-signed setup](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/dnssec-for-secondary/#set-up-pre-signed-dnssec) now also support NSEC3 as proof of non-existence.

For more information and how to enable NSEC3, refer to the [NSEC3 documentation](https://developers.cloudflare.com/dns/dnssec/enable-nsec3/).

## 2025-06-03

  
**Improved onboarding for Shopify merchants**   

Shopify merchants can now onboard to **O2O** automatically, without needing to contact support or community members.

What's new:

* **Automatic enablement** – O2O is available for all mutual Cloudflare and Shopify customers.
* **Branded record display** – Merchants see a Shopify logo in DNS records, complete with helpful tooltips.  
![Shopify O2O logo](https://developers.cloudflare.com/_astro/shop-dns-icon-o2o.Ca5DAZHL_1weoif.webp)
* **Checkout protection** – Workers and Snippets are blocked from running on the checkout path to reduce risk and improve security.

For more information, refer to the [provider guide](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/shopify/).

## 2025-02-02

  
**Removed unused meta fields from DNS records**   

Cloudflare is removing five fields from the `meta` object of DNS records. These fields have been unused for more than a year and are no longer set on new records. This change may take up to four weeks to fully roll out.

The affected fields are:

* the `auto_added` boolean
* the `managed_by_apps` boolean and corresponding `apps_install_id`
* the `managed_by_argo_tunnel` boolean and corresponding `argo_tunnel_id`

An example record returned from the API would now look like the following:

Updated API Response

```

{

  "result": {

    "id": "<ID>",

    "zone_id": "<ZONE_ID>",

    "zone_name": "example.com",

    "name": "www.example.com",

    "type": "A",

    "content": "192.0.2.1",

    "proxiable": true,

    "proxied": false,

    "ttl": 1,

    "locked": false,

    "meta": {

      "auto_added": false,

      "managed_by_apps": false,

      "managed_by_argo_tunnel": false,

      "source": "primary"

    },

    "comment": null,

    "tags": [],

    "created_on": "2025-03-17T20:37:05.368097Z",

    "modified_on": "2025-03-17T20:37:05.368097Z"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

For more guidance, refer to [Manage DNS records](https://developers.cloudflare.com/dns/manage-dns-records/).

## 2025-01-27

**Zone IDs and names on individual DNS records**

Records returned by the API will no longer contain the `zone_id` and `zone_name` fields. This change may take up to four weeks to fully roll out. The affected fields were deprecated with an End of Life (EOL) date of November 30, 2024.

## 2024-10-15

**Quote validation for TXT records added via dashboard**

When creating [TXT records](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#txt) via the dashboard you will now find:

* Field validation errors if double quotes `"` are added inconsistently.
* Automatically quoted TXT content upon save if no quotes exist in the record content field.

## 2024-10-07

**API support for per-record CNAME flattening**

Paid zones now have the option to flatten specific CNAME records. When using the API, specify the setting `cname_flatten` as `true` or `false`. Refer to the [documentation](https://developers.cloudflare.com/dns/cname-flattening/set-up-cname-flattening/#per-record) for details.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/changelog/","name":"Changelog"}}]}
```

---

---
title: Glossary
description: Definitions for terms used across Cloudflare DNS documentation.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Glossary

Review the definitions for terms used across Cloudflare's DNS documentation.

| Term                     | Definition                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| active zone              | A DNS zone that is active on Cloudflare requires changing its nameservers to Cloudflare's for management.                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| apex domain              | Apex domain is used to refer to a domain that does not contain a subdomain part, such as example.com (without www.). It is also known as "root domain" or "naked domain".                                                                                                                                                                                                                                                                                                                                                                                                            |
| CNAME setup              | Also known as partial setup, a CNAME setup allows you to use Cloudflare's reverse proxy without using Cloudflare for your authoritative nameservers.                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| DNS over HTTPS           | DNS over HTTPS (DoH) is a standard for encrypting DNS traffic via the HTTPS protocol, preventing tracking and spoofing of DNS queries.                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| DNS over TLS             | DNS over TLS (DoT) is a standard for encrypting DNS traffic using its own port (853) and TLS encryption.                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| DNS record               | DNS records are instructions that live in authoritative DNS servers and provide information about a domain, including what IP address is associated with that domain and how to handle requests for that domain.                                                                                                                                                                                                                                                                                                                                                                     |
| DNS server               | DNS servers translate human-readable domain names into IP addresses, eliminating the need to remember complex IP addresses.                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| DNS zone                 | A portion of the DNS namespace that is managed by a specific organization or administrator.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| Domain Name System (DNS) | The Domain Name System (DNS) is the phonebook of the Internet. DNS translates domain names to IP addresses.                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| EDNS Client Subnet (ECS) | ECS is a DNS extension that enables recursive DNS resolvers to include client IP address information in their DNS queries. Not all resolvers use ECS but, if they do, usually a part of the IP address is omitted. Sending ECS headers is generally intended to reduce latency and speed up content delivery in connection to [CDNs](https://developers.cloudflare.com/glossary/?term=cdn) and [load balancers](https://www.cloudflare.com/learning/performance/what-is-load-balancing/). The ECS mechanism is specified in [RFC 7871](https://www.rfc-editor.org/rfc/rfc7871.html). |
| hostname                 | The name given to a server or node on a network, often the public DNS name of a server.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| nameserver               | A nameserver is a dedicated server that translates human readable hostnames (www.example.com) into IP addresses. Nameservers like root servers, TLD servers, and [authoritative nameservers](https://developers.cloudflare.com/dns/nameservers/) are fundamental components of the Domain Name System (DNS).                                                                                                                                                                                                                                                                         |
| proxy status             | The proxy status of a DNS record defines whether requests for your domain will route through Cloudflare (proxied) or not (DNS-only). When a [DNS record is proxied](https://developers.cloudflare.com/dns/proxy-status/), requests are processed according to your configurations, and Cloudflare can optimize, cache, and protect your domain. Refer to [How Cloudflare works](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/) for details.                                                                                                          |
| zone apex                | Zone apex refers to the domain or subdomain on which the control of DNS records starts.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/glossary/","name":"Glossary"}}]}
```

---

---
title: Analytics and logs
description: View DNS query analytics and configure Logpush for DNS logs.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Analytics and logs

When you use Cloudflare DNS, you can access data about DNS queries through a variety of sources.

---

## Analytics

DNS analytics allow you to evaluate data about DNS queries to your zone.

You can [use the dashboard](#view-on-the-dashboard) to get insights quickly based on a [predefined set of dimensions](#available-dimensions), or [use the API](#explore-with-the-api) to have access to all fields available in the GraphQL DNS analytics schemas.

When using GraphQL, you also have the option to get data for DNS queries across all zones within a given Cloudflare account.

### Availability and limits

| Free                            | Pro    | Business | Enterprise |         |
| ------------------------------- | ------ | -------- | ---------- | ------- |
| Availability                    | Yes    | Yes      | Yes        | Yes     |
| Maximum time interval (zone)    | 7 days | 31 days  | 31 days    | 62 days |
| Maximum time interval (account) | 7 days | 7 days   | 7 days     | 62 days |
| Historical data (zone)          | 8 days | 31 days  | 31 days    | 62 days |
| Historical data (account)       | 8 days | 8 days   | 8 days     | 62 days |

### View on the dashboard

For a quick summary, view your DNS analytics on the dashboard:

[ Go to **Analytics** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/analytics) 

The DNS analytics dashboard contains [four main panels](#panels). The filters and time frame that you specify at the top of the page apply to all of them.

#### Available dimensions

* Query name
* Query type (same as DNS record type)
* Response code
* Data center
* Source IP
* Destination IP
* Protocol
* IP version

#### Panels

* **Query overview**: the number of queries and their distribution over time. This information is segmented by each of the [available dimensions](#available-dimensions) and the graph displays the top five values. You can select the dimensions through the different tabs above the graph and quickly filter for or exclude a certain value from the results by hovering over it and selecting **Filter** or **Exclude**.
* **Query statistics**: an overview of query metrics based on your filters and selected time frame. Namely, **Total queries**, **Average queries per second**, and **Average processing time**. The average processing time is displayed in milliseconds and includes upstream queries in the case of [flattened CNAME records](https://developers.cloudflare.com/dns/cname-flattening/).  
Note  
Processing time is different from response time. Response time would have to include information that is not available to Cloudflare, such as how long the query takes from the client to the resolver and from the resolver to Cloudflare (as your authoritative DNS provider).
* **DNS queries by data center**: a map indicating which Cloudflare data centers have handled DNS queries to your zone in the selected time period. You can also find a list of the ten top results and quickly filter for or exclude a certain data center from the results by hovering over it and selecting **Filter** or **Exclude**.
* **Queries by source**: a breakdown of the top five, ten, or fifteen results - based on your selection - and grouped by the [available dimensions](#available-dimensions).

### Explore with the API

For more detailed metrics, use the [GraphQL API](https://developers.cloudflare.com/analytics/graphql-api/). Refer to the GraphQL Analytics API documentation for guidance on how to [get started](https://developers.cloudflare.com/analytics/graphql-api/getting-started/).

The DNS analytics has two [schemas](https://developers.cloudflare.com/analytics/graphql-api/getting-started/querying-basics/):

* `dnsAnalyticsAdaptive`: Retrieve information about individual DNS queries.
* `dnsAnalyticsAdaptiveGroups`: Get reports on aggregate information only.

To get account-level data, you can set up queries similar to the following:

Get the last 10,000 queries resulting in NXDOMAIN

```

query GetLastNXDOMAINResponses {

  viewer {

    accounts(filter: { accountTag: "83a4527361bcdec24566fd7f837b6de5" }) {

      dnsAnalyticsAdaptive(

        limit: 10000

        filter: {

          date_geq: "2025-06-16",

          responseCode: "NXDOMAIN",

          date_leq: "2025-06-18"

        }

        orderBy: [datetime_DESC]

      ) {

        zoneTag

        queryName

        responseCode

        queryType

        datetime

      }

    }

  }

}


```

[Run in GraphQL API Explorer](https://graphql.cloudflare.com/explorer?query=I4VwpgTgngBA4mALgGQIYGdEDkAaARAeQFkBBASSwCUx0AHAewDt0aYBvAKBhgDcBLMAHdI7LtxioAxpPohGidAAoAZnwA2iSAC52E6bPkAVVAHMdAIgAcAZlQAWAKwAmAOzWAbAEYARpIAmYJJOju7uyn4uyjYu3u4BDuYwAL4AlKLi4n7MJIyoalCIfJLoJH6otIU8YIpiGdxqfAC2fIg6ngAMne21daoa2ul1GWWaAPomYMAWTu1ODgC07e7znu7mADQ9QxA0DMxgAML0ARa4hKQUG1t1I2CjapPTswtLK5bm19xJnzD0EAEQABCUB0AG1boVGnc8ABRADKBwAutc0pwhtwAF5MMDGEw-UCQKBYVBQn47OhMFhHAL48DQQxQWhgH4QprMobfDKc5IcJJAA&variables=N4XyA)

Get the overall query count per account

```

query GetTotalDNSQueryCount {

  viewer {

    accounts(filter: { accountTag: "83a4527361bcdec24566fd7f837b6de5" }) {

      dnsAnalyticsAdaptiveGroups(

        filter: {

          date_geq: "2025-05-01"

          date_leq: "2025-05-30"

        }

        limit: 1

      ) {

        count

      }

    }

  }

}


```

[Run in GraphQL API Explorer](https://graphql.cloudflare.com/explorer?query=I4VwpgTgngBA4mALgFQPaIIYBsAiA5AZQEVxoBhVEAO0RgG8AoGGANwEswB3Sep5mDAGNBlGgGcAFADM2WRJABc9AcNEoMAcyUAiABwBmDABYArACYA7PoBsARgBGggCZhBZ09etSnFqQYv21i4m2jAAvgCUvPz8TlRiAIJU2FCIbIKJThgADmksYHAQlNmSfDHMMnKK0eUxWfIA+hpgwDpmAAxmJgC07T3tttpltTD1YA1YLW2d-T367UMj4cMxWGwAtmyISrYrMFGMSyLUiHthw+fM52FAA&variables=N4XyA)

---

## Logs

Logs let Enterprise customers view [detailed information](https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/zone/dns%5Flogs/) about individual DNS queries.

For help setting up Logpush, refer to [Logpush](https://developers.cloudflare.com/logs/logpush/) documentation.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/additional-options/analytics/","name":"Analytics and logs"}}]}
```

---

---
title: Configure DNS zone defaults
description: Set default DNS settings applied to new zones in your account.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configure DNS zone defaults

While there are default values for DNS settings that Cloudflare applies to all new zones, Enterprise accounts have the option to configure their own DNS zone defaults according to their preference.

Warning

DNS zone defaults are only applied at the moment a new zone is created and will not impact already existing zones, nor zones that existed previously and are being revived.

Any of the values specified as default can later be adjusted within each zone, on the respective [**DNS Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/settings) or [**DNS Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) page.

## Steps

1. In the Cloudflare dashboard, go to the account **Settings** page.  
[ Go to **Configurations** ](https://dash.cloudflare.com/?to=/:account/configurations)
2. Go to **DNS Settings**. If these options are not displayed on your Cloudflare dashboard, you may need to reach out to your account team to have them added.
3. For **DNS zone defaults**, select **Configure defaults**.

The values you select for the listed settings will be automatically applied to new zones as you add them to your Cloudflare account.

## Available settings

* [Nameserver assignment](https://developers.cloudflare.com/dns/nameservers/nameserver-options/#assignment-method): Select your preferred nameserver type or assignment method that you want Cloudflare to use for your new zones. This setting applies both to primary zones ([full setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/)) and [secondary zones](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/).

For primary zones:

* [Multi-provider DNS](https://developers.cloudflare.com/dns/nameservers/nameserver-options/#multi-provider-dns): Control whether or not Cloudflare will consider `NS` records you add on the zone apex and if zones that contain external nameservers listed in the registrar will be activated.
* [Nameserver TTL](https://developers.cloudflare.com/dns/nameservers/nameserver-options/#nameserver-ttl): Control how long, in seconds, your nameserver (`NS`) records are cached. The default time-to-live (TTL) is 24 hours. This setting applies both to Cloudflare nameservers and [custom nameservers](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/).
* [SOA record](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#soa): Adjust values for the start of authority (SOA) record that Cloudflare creates for your zone.

For secondary zones:

* [Secondary DNS override](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/proxy-traffic/): Enable the options to use Cloudflare [proxy](https://developers.cloudflare.com/dns/proxy-status/) and add `CNAME` records at your zone apex.  
Multi-provider DNS does not apply as a setting for secondary zones, as this is already a required behavior for this setup. `SOA` record and the `NS` record TTL are defined on your external DNS provider and only transferred into Cloudflare.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/additional-options/dns-zone-defaults/","name":"Configure DNS zone defaults"}}]}
```

---

---
title: Reverse zones and PTR records
description: Set up reverse DNS zones and PTR records.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Reverse zones and PTR records

If you control your own IP prefix(es), you can set up reverse zones with PTR records to allow reverse DNS lookups.

## PTR records

PTR records specify the allowed hosts for a given IP address. They are the opposite of [A records ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-a-record) and used for reverse DNS lookups.

Historically, PTR records prevented outbound SMTP servers from being blocked by spam filters. However, more modern DNS records — [SPF, DKIM, and DMARC](https://developers.cloudflare.com/dns/manage-dns-records/how-to/email-records/#prevent-domain-spoofing) — provide better verifications of domain ownership.

Now, PTR records are primarily useful for those who own a dedicated IP space. They can help populate trace routes and security tools with human-readable domain names.

As PTR records are mainly used for reverse DNS lookups, they should preferably be added to reverse zones.

## Availability

The following Cloudflare customers can create reverse zones.

* Customers with an IPv4 or IPv6 address space can add the IPv4 or IPv6 reverse zone for their IP space to their account, and create the required PTR records for forward resolution.
* DNS Firewall customers need to contact their account team to add PTR records for the IPs used for their DNS Firewall clusters.

If your account does not meet these qualifications and you do not own the IP prefix you want to add PTR records on, contact the owner of the IP address based on a [whois lookup ↗](https://lookup.icann.org/).

## Set up a reverse zone

To set up a reverse zone, you need to create a reverse DNS zone and add PTR records for forward resolution.

### 1\. Create a reverse DNS zone

1. Within your account, click **Add** \> **Connect a domain**.
2. For your site name, use the reverse IP address:  
   * For IPv4 /24 prefixes, the pattern is:  
         * **IP prefix**: `<octet_1>.<octet_2>.<octet_3>.0/24`  
         * **Reverse zone address**: `<octet_3>.<octet_2>.<octet_1>.in-addr.arpa`  
   * For IPv4 /16 prefixes, the pattern is:  
         * **IP prefix**: `<octet_1>.<octet_2>.0.0/16`  
         * **Reverse zone address**: `<octet_2>.<octet_1>.in-addr.arpa`  
Example  
   * **IPv4 prefix**: `198.51.100.0/24`  
   * **Reverse zone**: `100.51.198.in-addr.arpa`  
   * For IPv6, consider the following examples:  
   * **IPv6 prefix**: `2001:DB8::0/32`  
   * **Reverse zone**: `8.b.d.0.1.0.0.2.ip6.arpa`  
   * **IPv6 prefix**: `2001:DB8::0/48`  
   * **Reverse zone**: `0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa`
3. If you are adding less than 200 PTR records, select the **Free** plan. If you are adding more, select a paid plan.
4. Skip the rest of the onboarding process.

### 2\. Add PTR records

1. In the Cloudflare dashboard, go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. For each IP within the prefix, add a PTR record using the least significant octet(s) as the subdomain.

IPv4 example

Suppose you have the following configuration:

* **Reverse zone**: `100.51.198.in-addr.arpa`
* **IP address**: `198.51.100.123`

The subdomain for the PTR record would be `123`, making the full domain for forward lookup `123.100.51.198.in-addr.arpa`.

| Type | Name | Domain name | TTL  |
| ---- | ---- | ----------- | ---- |
| PTR  | 123  | example.com | Auto |

IPv6 example

Suppose you have the following configuration:

* **Reverse zone**: `0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa`
* **IP address**: `2001:DB8::5`

The subdomain for the PTR record would be `5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0`, making the full domain for forward lookup `5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa`.

| Type | Name                                    | Domain name | TTL  |
| ---- | --------------------------------------- | ----------- | ---- |
| PTR  | 5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 | example.com | Auto |

### 3\. Set Cloudflare nameservers

Add the two Cloudflare nameservers provided for the zone at your Regional Internet Registry (RIR). The exact steps to update your nameservers will depend on the registry you are using.

After this process, your reverse zone will be activated and you can perform reverse DNS lookups.

## Other resources

While setting up reverse zones, the following third-party tools may be useful:

* [Reverse DNS record generator ↗](https://www.whatsmydns.net/reverse-dns-generator)
* [IPv6 subnet calculator ↗](https://www.internex.at/de/toolbox/ipv6)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/additional-options/reverse-zones/","name":"Reverse zones and PTR records"}}]}
```

---

---
title: Features and plans
description: Review information on all Cloudflare DNS features and their availability.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Features and plans

Cloudflare provides the following features for different [plans ↗](https://www.cloudflare.com/plans/).

## Features

### Advanced nameservers

**Link:**[Advanced nameservers](https://developers.cloudflare.com/dns/foundation-dns/advanced-nameservers/)

**Feature availability**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Included with [Foundation DNS](https://developers.cloudflare.com/dns/foundation-dns/)

### CNAME flattening

**Link:**[CNAME flattening](https://developers.cloudflare.com/dns/cname-flattening/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Can customize**

Pro plans and above can customize

* **Free:** No
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### Custom nameservers

**Link:**[Custom nameservers](https://developers.cloudflare.com/dns/nameservers/custom-nameservers/)

**Feature availability**
* **Free:** No
* **Pro:** No
* **Business:** Yes
* **Enterprise:** Yes

### DNS analytics

**Link:**[DNS analytics](https://developers.cloudflare.com/dns/additional-options/analytics/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Maximum time interval (zone)**
* **Free:** 7 days
* **Pro:** 31 days
* **Business:** 31 days
* **Enterprise:** 62 days

**Maximum time interval (account)**
* **Free:** 7 days
* **Pro:** 7 days
* **Business:** 7 days
* **Enterprise:** 62 days

**Historical data (zone)**
* **Free:** 8 days
* **Pro:** 31 days
* **Business:** 31 days
* **Enterprise:** 62 days

**Historical data (account)**
* **Free:** 8 days
* **Pro:** 8 days
* **Business:** 8 days
* **Enterprise:** 62 days

### DNSSEC

**Link:**[DNSSEC](https://developers.cloudflare.com/dns/dnssec/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### DNS Firewall

**Link:**[DNS Firewall](https://developers.cloudflare.com/dns/dns-firewall/)

**Feature availability**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Paid add-on

**Historical data**
* **Free:** N/A
* **Pro:** N/A
* **Business:** N/A
* **Enterprise:** 62 days

**Maximum time interval**
* **Free:** N/A
* **Pro:** N/A
* **Business:** N/A
* **Enterprise:** 62 days

### Full zone setup

**Link:**[Full zone setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### Partial zone setup

**Link:**[Partial zone setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)

**Feature availability**
* **Free:** No
* **Pro:** No
* **Business:** Yes
* **Enterprise:** Yes

### DNS records management

**Link:**[DNS records management](https://developers.cloudflare.com/dns/manage-dns-records/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Number of records per zone**
* **Free:** 1,000 for zones created before `2024-09-01 00:00:00 UTC`  
 200 for zones created on or after `2024-09-01 00:00:00 UTC`
* **Pro:** 3,500
* **Business:** 3,500
* **Enterprise:** 3,500 (can be increased)

### DNS record comments

**Link:**[DNS record comments](https://developers.cloudflare.com/dns/manage-dns-records/reference/record-attributes/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Character limit**
* **Free:** 100
* **Pro:** 500
* **Business:** 500
* **Enterprise:** 500

**Comments per record**
* **Free:** 1
* **Pro:** 1
* **Business:** 1
* **Enterprise:** 1

### DNS record tags

**Link:**[DNS record tags](https://developers.cloudflare.com/dns/manage-dns-records/reference/record-attributes/)

**Feature availability**
* **Free:** No
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Name character limit (everything before the colon)**
* **Free:** N/A
* **Pro:** 32
* **Business:** 32
* **Enterprise:** 32

**Value character limit (everything after the colon)**
* **Free:** N/A
* **Pro:** 100
* **Business:** 100
* **Enterprise:** 100

**Tags per record**
* **Free:** N/A
* **Pro:** 20
* **Business:** 20
* **Enterprise:** 20

### DNS zone transfers

**Link:**[DNS zone transfers](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/)

**Feature availability**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

### Subdomain zone setup

**Link:**[Subdomain zone setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/)

**Feature availability**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

### Subdomain delegation

**Link:**[Subdomain delegation](https://developers.cloudflare.com/dns/manage-dns-records/how-to/subdomains-outside-cloudflare/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### Reverse zones

**Link:**[Reverse zones](https://developers.cloudflare.com/dns/additional-options/reverse-zones/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/reference/all-features/","name":"Features and plans"}}]}
```

---

---
title: Analytics API properties
description: API properties that you can use in API requests for Cloudflare DNS analytics.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Analytics API properties

This page describes API properties that you can use in requests to the [DNS analytics API](https://developers.cloudflare.com/api/resources/dns/subresources/analytics/subresources/reports/methods/get/).

Warning

The [DNS analytics API](https://developers.cloudflare.com/api/resources/dns/subresources/analytics/subresources/reports/methods/get/), along with the following [API properties](https://developers.cloudflare.com/dns/reference/analytics-api-properties/), will be deprecated soon.

To access the new analytics dashboard, go to [**DNS Analytics** ↗](https://dash.cloudflare.com//?to=/:account/:zone/dns/analytics). Refer to [Analytics and logs](https://developers.cloudflare.com/dns/additional-options/analytics/) for details.

## Metrics

A metric is a numerical value based on an attribute of the data, for example a query count.

In API requests, metrics are set in the `metrics` parameter. If you need to list multiple metrics, separate them with commas.

| Metric             | Name                          | Example | Unit                 |
| ------------------ | ----------------------------- | ------- | -------------------- |
| queryCount         | Query count                   | 1000    | Count                |
| uncachedCount      | Uncached query count          | 1       | Count                |
| staleCount         | Stale query count             | 1       | Count                |
| responseTimeAvg    | Average response time         | 1.0     | Time in milliseconds |
| responseTimeMedian | Median response time          | 1.0     | Time in milliseconds |
| responseTime90th   | 90th percentile response time | 1.0     | Time in milliseconds |
| responseTime99th   | 99th percentile response time | 1.0     | Time in milliseconds |

## Dimensions

Dimensions can be used to break down the data by given attributes.

In API requests, dimensions are set in the `dimensions` parameter. If you need to list multiple dimensions, separate them with commas.

| Dimension          | Name                 | Example     | Notes                                                                                                                                       |
| ------------------ | -------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| queryName          | Query Name           | example.com |                                                                                                                                             |
| queryType          | Query Type           | AAAA        | [Types defined by IANA ↗](http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4). Unknown types are empty.   |
| responseCode       | Response Code        | NOERROR     | [Response codes defined by IANA ↗](http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6). Always uppercase. |
| responseCached     | Response Cached      | Cached      | Either Cached or Uncached.                                                                                                                  |
| coloName           | Colo Name            | SJC         | PoP code.                                                                                                                                   |
| origin             | Origin               | 2001:db8::1 | Origin used to resolve the query. Empty if N/A or if the query was answered from cache.                                                     |
| dayOfWeek          | Day Of Week          | 1           | Break down by day of week. Monday is 1, and Sunday is 7.                                                                                    |
| tcp                | TCP                  | 1           | Either 1 or 0 depending on the protocol used.                                                                                               |
| ipVersion          | IP Version           | 6           | IP protocol version used (currently 4 or 6).                                                                                                |
| querySizeBucket    | Query Size Bucket    | 16-31       | Query size bucket by multiples of 16.                                                                                                       |
| responseSizeBucket | Response Size Bucket | 16-31       | Response size bucket by multiples of 16.                                                                                                    |

## Filters

Filters use the form `dimension operator expression`, where each part corresponds to the following:

* **Dimension**: Specifies the [dimension](#dimensions) to filter on. For example, `queryName`.
* **Operator**: Defines the type of filter match to use. Operators are specific to dimensions.
* **Expression**: States the values to include or exclude from the results. Expressions use regular expression (regex) syntax.

### Filter operators

| Operator | Name                     | Example                | Description                                                        | URL Encoded |
| -------- | ------------------------ | ---------------------- | ------------------------------------------------------------------ | ----------- |
| \==      | Equals                   | queryName==example.com | Return results where queryName is exactly example.com.             | %3D%3D      |
| !=       | Does not equal           | responseCode!=NOERROR  | Return results where responseCode is different from NOERROR.       | !%3D        |
| \>       | Greater than             | dimension>1000         | Return results where a dimension is greater than 1000.             | %3E         |
| <        | Less than                | dimension<1000         | Return results where a dimension is less than 1000.                | %3C         |
| \>=      | Greater than or equal to | dimension>=1000        | Return results where a dimension is greater than or equal to 1000. | %3E%3D      |
| <=       | Less than or equal to    | dimension<=1000        | Return results where a dimension is less than or equal to 1000.    | %3C%3D      |

### Combining filters

Combine filters using `OR` and `AND` boolean logic:

* `AND` takes precedence over `OR` in all expressions.
* The `OR` operator is defined using a comma `,` or the `OR` keyword surrounded by whitespace.
* The `AND` operator is defined using a semicolon `;` or the `AND` keyword surrounded by whitespace.  
Note  
Note that the semicolon is a reserved character in URLs ([RFC 1738 ↗](https://www.rfc-editor.org/rfc/rfc1738)) and should be percent-encoded as `%3B`.

Examples using OR

* `responseCode==NOERROR,responseCode==NXDOMAIN` indicates that response code is either `NOERROR` or `NXDOMAIN`.
* `coloName==SJC OR coloName==LAX` indicates queries in either `SJC` or `LAX`.

Examples using AND

* `responseCode==NOERROR;queryType==AAAA` indicates that response code is `NOERROR` and query type is `AAAA`.
* `queryType==AAAA AND coloName==SJC` indicates `AAAA` queries in `SJC`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/reference/analytics-api-properties/","name":"Analytics API properties"}}]}
```

---

---
title: Concepts
description: Migrate and manage DNS on Cloudflare.
image: https://developers.cloudflare.com/cf-twitter-card.png
---

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

[Skip to content](#%5Ftop) 

# Concepts

Migrating your DNS from an on-premises BIND solution to a cloud-based provider like Cloudflare can offer significant benefits in terms of performance, security, and manageability. However, a successful migration requires careful planning and execution. This guide outlines best practices to ensure a smooth transition.

## Objectives

By the end of this module, you will be able to:

* Plan and take inventory of your DNS migration.
* Prepare for the migration with minimal downtime.
* Learn how to make the actual switch to Cloudflare.
* Verify and stabilize after your migration.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/learning-paths/","name":"Learning Paths"}},{"@type":"ListItem","position":3,"item":{"@id":"/learning-paths/dns-best-practices/concepts/","name":"Concepts"}}]}
```

---

---
title: Domain Connect
description: Learn how to onboard your templates to use Domain Connect with Cloudflare as DNS provider.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Domain Connect

If you are a service provider, consider this page for information on how Cloudflare supports [Domain Connect ↗](https://www.domainconnect.org/) and how you can onboard your template.

## What is Domain Connect

Domain Connect is an open standard that allows service providers - such as email or web hosting platforms - to make it easier for their end users to configure functionality, without having to manually edit DNS records.

This is achieved with templates that close the gap between necessary configurations (required by the service provider) and necessary DNS records changes (that must happen at the authoritative DNS provider).

In practice, this means that when a user that owns `example.com` and has Cloudflare as their authoritative DNS wants to use your service, instead of having to manually update their DNS records, they will only have to authenticate themselves and the necessary changes will be applied automatically.

## Setup

### Before you begin

* Note that Cloudflare only supports the [Domain Connect synchronous flow ↗](https://www.domainconnect.org/getting-started/).
* Domain Connect templates and tools are published on GitHub, so you must have a GitHub account and be familiar with [GitHub forks and pull requests ↗](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks).

### 1\. Add templates to the repository

Domain Connect templates are published and maintained on a GitHub repository.

1. Create a fork of the [templates repository ↗](https://github.com/Domain-Connect/Templates).
2. Add your template. You can create a copy of one of the existing templates and edit it according to your needs.  
   * Refer to the [Domain Connect Specification ↗](https://github.com/Domain-Connect/spec/blob/master/Domain%20Connect%20Spec%20Draft.adoc) for details on the different available fields.  
   Note  
   Not all fields (properties) are supported by Cloudflare, and some will be mandatory for onboarding your template. Refer to the [properties support](#properties-support) section below for details.  
   * If present, you must set the `syncBlock` field on your template to `false`. This means the template flow will be synchronous, which is the only option supported by Cloudflare.  
   * You must also provide a synchronous public key domain (`syncPubKeyDomain` [1](#user-content-fn-1)). When your template is in use, synchronous calls will be digitally signed.
3. Make sure you follow the naming format defined by Domain Connect: `<providerId>.<serviceId>.json`.

Tip

You can use Domain Connect's [linter tool ↗](https://github.com/Domain-Connect/dc-template-linter) with the option `-cloudflare` enabled to check your template against Cloudflare specific rules.

1. Submit a pull request to have your templates added to the repository.

Once your pull request has been reviewed and merged, contact Cloudflare as specified below.

### 2\. Contact Cloudflare to onboard your template

When your template is onboarded, a graphical user interface flow will be available to your end users.

Send an email to `domain-connect@cloudflare.com`, including the following information:

1. List of templates you want to onboard, with their corresponding GitHub hyperlinks.
2. Fully qualified domain names to query for the `syncPubKeyDomain`[1](#user-content-fn-1) TXT records.
3. A logo to be displayed as part of the Domain Connect flow. Preferably in `SVG` format.
4. The default [proxy status](https://developers.cloudflare.com/dns/proxy-status/) you would like Cloudflare to set for `A`, `AAAA`, and `CNAME` records that are part of your templates. Proxying other record types is not supported.  
Note  
Proxy status is applied per template. If needed, organize the records in different templates to specify a different default proxy status per template. Once the records have been created, the domain owner can always change the proxy status for `A`, `AAAA`, and `CNAME` records later.
5. (Optional) A Cloudflare [account ID](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/) for you to test the flow.  
If you have a [DNS provider discovery ↗](https://github.com/Domain-Connect/spec/blob/master/Domain%20Connect%20Spec%20Draft.adoc#dns-provider-discovery) automation in place and will not list new DNS providers manually, Cloudflare can initially restrict your template to be exposed to the specified account only. Once you confirm everything is working as expected, Cloudflare will publish your template on the discovery endpoint, to be picked up by your automation.

## Properties support

In the [Domain Connect Specification ↗](https://github.com/Domain-Connect/spec/blob/master/Domain%20Connect%20Spec%20Draft.adoc) you will find the following properties:

* Properties that you can use with your [apply template URL ↗](https://github.com/Domain-Connect/spec/blob/master/Domain%20Connect%20Spec%20Draft.adoc#apply-template).
* Properties for [defining the template itself ↗](https://github.com/Domain-Connect/spec/blob/master/Domain%20Connect%20Spec%20Draft.adoc#template-definition).
* Properties for defining the individual [DNS records ↗](https://github.com/Domain-Connect/spec/blob/master/Domain%20Connect%20Spec%20Draft.adoc#template-record).

While most of these are supported by Cloudflare, some are required and others are not supported.

Linter tool

Use Domain Connect's [linter tool ↗](https://github.com/Domain-Connect/dc-template-linter) with the option `-cloudflare` enabled to check your template against Cloudflare specific rules.

### Apply template URL

For the full list, refer to the [Domain Connect Specification ↗](https://github.com/Domain-Connect/spec/blob/master/Domain%20Connect%20Spec%20Draft.adoc). Below are the details specific to Cloudflare.

* **Redirect URI**: Domain Connect's documentation states that it must be scoped to the `syncRedirectDomain` from the template, or the request must be signed. Cloudflare requires the request to be signed and, as such, does not check if the `redirect_uri` is scoped to the `syncRedirectDomain`.
* **State**: Is not supported and will be ignored.
* **Service Name**: Is not supported and will be ignored.
* **Signature**: Required. It also must be the last query parameter.
* **Key**: Required. You must publish your public key and place it in a DNS TXT record on a domain specified in the template as `syncPubKeyDomain`. To allow for key rotation, the hostname of the TXT record must be appended as another variable on the query string of the form.

### Template definition

For the full list, refer to the [Domain Connect Specification ↗](https://github.com/Domain-Connect/spec/blob/master/Domain%20Connect%20Spec%20Draft.adoc). Below are the details specific to Cloudflare.

* **Service Provider Name**: Will be displayed on the user interface.
* **Service Name**: Will **not** be displayed on the user interface.
* **Logo**: If present, will be displayed on the user interface.
* **Synchronous Block**: Is not supported and will be ignored. Cloudflare only supports the synchronous flow.
* **Shared**: Is not supported and will be ignored.
* **Shared Service Name**: Is not supported and will be ignored.
* **Synchronous Public Key Domain**: Required. Cloudflare only supports the synchronous flow and always checks for signature.
* **Synchronous Redirect Domains**: Is not supported and will be ignored. Cloudflare looks at the `redirect_uri` provided in the signed apply template URL.
* **Multiple Instance**: Is not supported and will be ignored.
* **Warn Phishing**: Is not supported and will be ignored.
* **Host Required**: Is not supported and will be ignored.

### DNS records

For the full list, refer to the [Domain Connect Specification ↗](https://github.com/Domain-Connect/spec/blob/master/Domain%20Connect%20Spec%20Draft.adoc). Below are the details specific to Cloudflare.

* **Essential**: Is not supported and will be ignored.
* **TXT Conflict Matching Mode**: Is not supported and will be ignored.
* **TXT Conflict Matching Prefix**: Is not supported and will be ignored.

#### Custom record types

The following record types are described in the [extensions/exclusions ↗](https://github.com/Domain-Connect/spec/blob/master/Domain%20Connect%20Spec%20Draft.adoc#extensionsexclusions) section of the Domain Connect Specification. Below are the details specific to Cloudflare.

* **APEXCNAME**: This custom record type is not supported and will cause the onboarding to fail. You can use a standard CNAME record instead, as Cloudflare automatically applies [CNAME flattening](https://developers.cloudflare.com/dns/cname-flattening/) at the zone apex.
* **REDIR301** and **REDIR302**: When applied, these records are converted to zone-specific [bulk redirect](https://developers.cloudflare.com/rules/url-forwarding/bulk-redirects/) rules. If a zone has existing bulk redirects before applying the template, they will be replaced.

## Template updates

Since September, 2024, template updates are picked up by an automation.

The automation compares the template version number in Cloudflare with the authoritative source of the template on the Internet. This check runs multiple times a day. Although Cloudflare cannot guarantee when exactly each update will be picked up, the process is expected to take no longer than eight hours.

Note

The authoritative source must be in raw `json` format for the automation to work correctly, as in [this example ↗](https://raw.githubusercontent.com/Domain-Connect/Templates/master/exampleservice.domainconnect.org.template1.json).

If the source template is unavailable, or technically invalid, Cloudflare will keep the previous template in use until the updated version is fixed.

You can contact Cloudflare to opt out of the automatic updates. Once the automation is disabled, you can request template updates individually, by writing to `domain-connect@cloudflare.com`.

### Troubleshooting

Send an email to `domain-connect@cloudflare.com` with the following information:

1. Detailed description of what is wrong, including:  
   * Date and time when the issue occurred.  
   * The `providerId` and `serviceId` of the template.  
   * Description of what the request did.  
   * Description of what you expected to happen.
2. A [HAR file](https://developers.cloudflare.com/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/#generate-a-har-file) attachment containing the problematic update.

### Validation errors

The most common issues after template onboarding are validation errors, typically caused by `syncPubKeyDomain` TXT records.

You can fix these by republishing the signature, using tools such as the one provided by [Domain Connect ↗](https://exampleservice.domainconnect.org/sig). Additionally, you can test signature validation with this [public key debug tool ↗](https://github.com/kerolasa/dc-debug-pubkey).

## Footnotes

1. A domain that can be queried for `TXT` records containing a public key to verify your digital signature. Refer to [digitally signed requests ↗](https://github.com/Domain-Connect/spec/blob/master/Domain%20Connect%20Spec%20Draft.adoc#digitally-sign-requests) for details. [↩](#user-content-fnref-1) [↩2](#user-content-fnref-1-2)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/reference/domain-connect/","name":"Domain Connect"}}]}
```

---

---
title: Recommended third-party tools
description: List of recommended third-party tools for DNS testing and troubleshooting.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Recommended third-party tools

You can use the third-party tools listed below to test and troubleshoot DNS settings.

* [DNSViz ↗](https://dnsviz.net): A web-based tool for visualizing the status of a DNS zone to understand and troubleshoot the deployment of DNS Security Extensions (DNSSEC).
* [Dig Web Interface ↗](https://digwebinterface.com): An online DNS lookup tool based on the command line interface `dig`. Users can skip the process of entering commands with complicated parameters in the terminal by entering the same information in this web tool and getting the same results.
* [dns.google ↗](https://dns.google): A web-based tool, similar to Dig Web Interface, where users can get DNS responses for specific queries.
* [Mess with DNS ↗](https://messwithdns.net): An educational resource that encourages users to experiment with DNS records by providing users with a domain where they are free to play around and break things during the learning process.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dns/","name":"DNS"}},{"@type":"ListItem","position":3,"item":{"@id":"/dns/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/dns/reference/recommended-third-party-tools/","name":"Recommended third-party tools"}}]}
```

---

---
title: Google tag gateway for advertisers
description: Deploy Google measurement tags from your domain for improved ad signal recovery.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Google tag gateway for advertisers

Google tag gateway for advertisers allows website owners using Cloudflare as a CDN to get the most out of ad measurement tools with just a few clicks. It allows you to deploy Google scripts using your own domain, enhancing data privacy and improving signal measurement recovery. Unlike standard setups where tags are requested from a Google domain, Google tag gateway for advertisers loads the tag from your domain and sends measurement events to your domain, where they are forwarded to Google.

Learn more about why we built it and how it works in our [blog post ↗](https://blog.cloudflare.com/google-tag-gateway-for-advertisers/).

## Pricing

Google tag gateway for advertisers is free to use. Requests routed through the gateway do not count toward usage or billing for other Cloudflare products such as [CDN](https://developers.cloudflare.com/cache/), [WAF](https://developers.cloudflare.com/waf/), or [Bot Management](https://developers.cloudflare.com/bots/).

## Get started

Site owners can enable this feature in one of two ways: through the Google tag console, or through the [Cloudflare dashboard ↗](https://dash.cloudflare.com/?to=/:account/tag-management/google-tag-gateway).

### Configure in Google Tag Manager

The fastest way to set up Google tag gateway for advertisers is in Google Tag Manager. [Follow the steps in Google's Help Center ↗](https://support.google.com/analytics/answer/16061641).

### Configure in the Cloudflare dashboard

Note

Your Cloudflare dashboard user must have one of the following [Account Roles](https://developers.cloudflare.com/fundamentals/manage-members/roles/#account-scoped-roles): Super Administrator, Administrator or Zaraz Admin. If you are using Domain Scoped Roles, your [Domain Role](https://developers.cloudflare.com/fundamentals/manage-members/roles/#domain-scoped-roles) must be Domain Administrator.

1. In the Cloudflare dashboard, go to the **Google Tag Gateway** page.  
[ Go to **Google Tag Gateway** ](https://dash.cloudflare.com/?to=/:account/tag-management/google-tag-gateway)
2. Select your domain.
3. Enable the toggle for **Turn on and configure Google tag gateway**.
![Google tag gateway for advertisers configuration](https://developers.cloudflare.com/_astro/google-tag-configuration.DAsbB12B_Z2mnQya.webp) 
1. Add your Google tag ID and the path on your website reserved for the Google tag. The [Google tag ID ↗](https://support.google.com/analytics/answer/9539598?hl=en) can be found in the Google Tag Experience dashboard. The measurement path is an unused path on your site that will load Google Tag Manager and all subsequent measurement requests.
![Add to ID and path](https://developers.cloudflare.com/_astro/google-tag-id-path.FiWAyHgy_Z1n6SmD.webp) 
1. Once you click **Save**, Google tag gateway for advertisers will be enabled on your zone. If you already have a GTM script on your website, this First Party Tag will override the existing script.

Now that you have authenticated into your Cloudflare account and configured GTM in first-party mode, your Google Tags will be loaded using `https://your-domain/measurement-path/...`and subsequent measurement requests will be served by Cloudflare.

## Zone-level configuration

Google tag gateway for advertisers is configured at the zone level. When you enable it for a zone (for example, `example.com`), it applies to all hostnames and subdomains within that zone, including custom hostnames. Currently, it is not possible to enable or disable the feature for individual subdomains independently. [Configuration Rules](https://developers.cloudflare.com/rules/configuration-rules/) cannot be used to control or disable the tag injection on specific subdomains.

### Handle subdomain-specific logic with triggers

If you need different tag behavior for specific subdomains (for example, only firing certain tags on `shop.example.com`), you can use [Google Tag Manager triggers ↗](https://support.google.com/tagmanager/answer/7679316) to control when tags fire. For example, you can create a trigger condition like **Page Hostname** equals `shop.example.com` to restrict a tag to a specific subdomain.

This approach lets you maintain a single zone-wide Google tag gateway configuration while still customizing tag behavior per subdomain.

## Related resources

* [Google Developer Docs: Set up Google tag gateway for advertisers ↗](https://developers.google.com/tag-platform/tag-manager/gateway/setup-guide?setup=auto)
* [Google Help Center: Set up Google tag gateway for advertisers in the Google tag with Cloudflare ↗](https://support.google.com/tagmanager/answer/16061406)
* [Google Help Center: Set up Google tag gateway for advertisers in Google Tag Manager with Cloudflare ↗](https://support.google.com/analytics/answer/16061641)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/google-tag-gateway/","name":"Google tag gateway for advertisers"}}]}
```

---

---
title: Health Checks
description: Monitor origin server availability and get notified of status changes.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Health Checks

Smart Shield

This functionality is now offered as part of Cloudflare's origin server safeguard, Smart Shield. [Learn more](https://developers.cloudflare.com/smart-shield/).

Standalone Health Checks monitors an IP address or hostname for origin servers or applications and notifies you in near real-time if there happens to be a problem.

A health check is a service that runs on Cloudflare's edge network to monitor whether an origin server is online. This allows you to view the health of your origin servers even if there is only one origin or you do not yet need to balance traffic across your infrastructure.

Health Checks support various configurations to hone in on what you can check, including response codes, protocol types, and intervals. You can specify a particular path if an origin server serves multiple applications or check a larger subset of response codes for your staging environment. All of these options allow you to properly target your Health Check, providing a precise picture of what is wrong with an origin server.

Note

Standalone Health Checks are different from health monitors associated with load balancers. For more details about health monitors, refer to the [Load Balancing documentation](https://developers.cloudflare.com/load-balancing/monitors/).

---

## Features

###  Health Checks Analytics 

You can use Health Checks Analytics to evaluate origin uptime, latency, failure reason, and specific event logs to debug possible origin issues.

[ Use Health Checks Analytics ](https://developers.cloudflare.com/health-checks/health-checks-analytics/) 

---

## Related products

**[Load Balancing](https://developers.cloudflare.com/load-balancing/)** 

Cloudflare Load Balancing distributes traffic across your [endpoints](https://developers.cloudflare.com/load-balancing/understand-basics/load-balancing-components/), which reduces endpoint strain and latency and improves the experience for end users.

---

## Availability

| Free             | Pro | Business | Enterprise |       |
| ---------------- | --- | -------- | ---------- | ----- |
| Availability     | No  | Yes      | Yes        | Yes   |
| Number of checks | 0   | 10       | 50         | 1,000 |
| Analytics        | No  | Yes      | Yes        | Yes   |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/health-checks/","name":"Health Checks"}}]}
```

---

---
title: Get started
description: Create and configure Health Checks to monitor your origin servers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

Smart Shield

This functionality is now offered as part of Cloudflare's origin server safeguard, Smart Shield. [Learn more](https://developers.cloudflare.com/smart-shield/).

This guide will get you started with creating and managing configured Health Checks.

## Create a Health Check

1. In the Cloudflare dashboard, go to the **Health Checks** page.  
[ Go to **Health Checks** ](https://dash.cloudflare.com/?to=/:account/:zone/traffic/health-checks)
2. Select **Create** and fill out the form, paying special attention to:  
   * The values for **Interval** and **Check regions**, because decreasing the **Interval** and increasing **Check regions** may increase the load on your origin server.  
   * **Retries**, which specify the number of retries to attempt in case of a timeout before marking the origin as unhealthy.  
   * **Response body**, which specifies a substring that must be present in the first 10 KB of the response body for the check to succeed.
3. Select **Save and Deploy**.

## Manage Health Checks

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com) and select your account and domain.
2. Go to **Traffic** \> **Health Checks**.
3. Navigate to your health check and select **Edit**.
4. Edit your Health Check.
5. Select **Save**.

Note

You can also enable, disable, or delete configured Health Checks.

Note

Authenticated origin pull is not supported by Standalone Health Checks.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/health-checks/","name":"Health Checks"}},{"@type":"ListItem","position":3,"item":{"@id":"/health-checks/get-started/","name":"Get started"}}]}
```

---

---
title: Health Checks Analytics
description: View Health Checks status history and response time analytics.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Health Checks Analytics

Smart Shield

This functionality is now offered as part of Cloudflare's origin server safeguard, Smart Shield. [Learn more](https://developers.cloudflare.com/smart-shield/).

Once you have set up a standalone Health Check including notification emails, use Health Check Analytics to debug possible origin issues.

To access health check analytics:

1. In the Cloudflare dashboard, go to the **Health Check Analytics** page.  
[ Go to **Health Check Analytics** ](https://dash.cloudflare.com/?to=/:account/:zone/traffic/health-check-analytics)

You can evaluate origin uptime, latency, failure reason, and specific event logs:

* **Health Checks By Uptime**: Shows the percentage of uptime for individual origins over time.
* **Health Checks By Failure Reason**: Shows a breakdown of failures by the specific reason. Refer to [common error code causes and solutions below](#common-error-codes).
* **Health Checks By Latency**: Shows average latency – measured in round trip time — for individual origins over time.
* **Event Log**: Shows individual health check data.  
   * Select each record for additional details on **Round trip time**, the **Failure Reason**, the **Average Waterfall** (showing chronological data about request stages), **Response status code**, and more.  
   * Note that **Global** is not a configured region; it represents the aggregated data from all enabled regions.

## Common error codes

### TCP connection failed

#### Cause

Health Checks failed to establish a TCP connection to your origin server.

#### Solution

This typically occurs when there is a network failure between Cloudflare and your origin, and/or a firewall refuses to allow our connection. Ensure your network and firewall configurations are not interfering with traffic.

### HTTP timeout occurred

#### Cause

The origin failed to return an HTTP response within the timeout configured. This happens if you have the timeout set to a low number. For example, one to two seconds.

#### Solution

Cloudflare recommends increasing the HTTP response timeout to allow the origin server to respond.

### Response code mismatch error

#### Cause

Cloudflare receives an HTTP status code that does not match the values defined in the `expected_codes` property of your Health Check configuration.

#### Solution

Response codes must match the `expected_codes`. Confirm the values are correct by comparing the expected response codes and the status code received in the Event Log.

#### ​​Alternate cause

You may also see this issue if you have a Health Check configured to use HTTP connections and your origin server is redirecting to HTTPS. In this case, the response code will often be `301`, `302`, or `303`.

#### Solution

Change your Cloudflare Health Check configuration to use HTTPS or set the value of `follow_redirect` to `true` so that Cloudflare can resolve the correct status code.

### Response body mismatch error

#### Cause

The response body returns from your origin server and does not include the (case-insensitive) value of `expected_body` configured in your Health Check.

Note

We only read the first 10 KB of the response. If you return a larger response, and the `expected_body` is not in the first 10 KB, the Health Check will fail.

#### Solution

Ensure the `expected_body` is in the first 10 KB of the response body. ​​

### TLS untrusted certificate error

#### Cause

The certificate is not trusted by a public Certificate Authority (CA).

#### Solution

If you’re using a self-signed certificate, Cloudflare recommends either using a publicly trusted certificate or setting the `allow_insecure` property on your Health Check to `true`.

### TLS name mismatch error

#### Cause

Our Health Check (client) was not able to match a name on the server certificate to the hostname of the request.

#### Solution

Inspect your Health Check configuration to confirm that the `header` value set in the Cloudflare Health Check is correct.

### TLS protocol error

#### Cause

This error can occur if you are using an older version of TLS or your origin server is not configured for HTTPS.

#### Solution

Ensure that your origin server supports TLS 1.2 or greater and is configured for HTTPS.

### TLS unrecognized name error

#### Cause

The server did not recognize the name provided by the client. When a host header is set, this is set as the ServerName in the initial TLS handshake. If it is not set, Cloudflare will not provide a ServerName, which can cause this error.

#### Solution

Set the host header in your Health Check object.

### ​​No route to host error

#### Cause

The IP address cannot be reached from Cloudflare’s network. Common causes are ISP or hosting provider network issues (e.g. BGP level), or that the IP does not exist.

#### Solution

Ensure IP is accurate, and check if there is an ISP or hosting provider network issue.

### TCP Timeout

#### Cause

Data transmission was not acknowledged and the retransmit of data did not succeed.

#### Solution

Confirm whether the SYN-ACK for the handshake takes place at your origin and contact [Cloudflare support](https://developers.cloudflare.com/support/contacting-cloudflare-support/).

### ​​Network Unreachable

#### Cause

Cloudflare cannot connect to the origin web server due to network unavailability. This is usually caused by a network issue or incorrect origin IP.

#### Solution

Check the IP entered for the origin in Cloudflare’s Health Checks configuration or the IP returned via DNS for the origin hostname.

### HTTP Invalid Response

#### Cause

Usually caused by an HTTP 502 error or bad gateway.

#### Solution

Ensure the origin web server responds to requests and that no applications have crashed or are under high load.

### DNS Unknown Host

#### Cause

The origin web server hostname does not exist.

#### Solution

Confirm the origin web server resolves to an IP address.

### Connection Reset by Peer

#### Cause

A network error occurred while the client received data from the origin web server.

#### Solution

Confirm whether the origin web server is experiencing a high amount of traffic or an error.

### Monitor Configuration Error

#### Cause

There was a configuration error in the Health Check and no checks were run against the origin.

#### Solution

Review your Health Check configuration to ensure it matches an expected request to your origin.

### ​​DNS Internal

#### Cause

The origin web server’s hostname resolves to an internal or restricted address. No checks are run against this origin.

#### Solution

Cloudflare does not allow use of an origin web server hostname that resolves to a Cloudflare IP.

### Other Failure

#### Cause

If the failure cannot be classified as any other type of failure mentioned above.

#### Solution

Contact [Cloudflare support](https://developers.cloudflare.com/support/contacting-cloudflare-support/).

## Set up alerts

You can configure alerts to notify you of any changes in your health check status.

Health Checks status notification

**Who is it for?**

Customers who want to be warned about changes to server health as determined by [health checks](https://developers.cloudflare.com/health-checks/).

**Other options / filters**

Available filters include:

* You can search for and add health checks from your list of health checks.
* You can choose a trigger to fire the notification when your server becomes **unhealthy**, **healthy**, or **either healthy or unhealthy**.
**Included with**

Professional plans or higher.

**What should you do if you receive one?**

Review your [health check analytics](https://developers.cloudflare.com/health-checks/health-checks-analytics/#common-error-codes).

Refer to [Cloudflare Notifications](https://developers.cloudflare.com/notifications/get-started/) for more information on how to set up an alert.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/health-checks/","name":"Health Checks"}},{"@type":"ListItem","position":3,"item":{"@id":"/health-checks/health-checks-analytics/","name":"Health Checks Analytics"}}]}
```

---

---
title: Health Checks regions
description: Cloudflare data center regions used for Health Checks monitoring.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Health Checks regions

Cloudflare has data centers in [hundreds of cities worldwide ↗](https://www.cloudflare.com/network/). Health checks do not run from every single of these data centers as this would result in numerous requests to your servers. Instead, you are able to choose between one and thirteen regions from which to run health checks. Cloudflare will run Health Checks from three data centers in each region that you select.

Note

The exact location of these data centers are subject to change at any moment.

The Internet is not the same everywhere around the world and your users may not have the same experience on your application according to where they are. Running Health Checks from different regions lets you know the health of your application from the point of view of the Cloudflare network in each of these regions.

Analytics are presented at two levels:

* Regional Aggregates: Combined results from the three data centers within a specific region.
* Global Aggregates: Total results across all configured regions and data centers.

In the event log, entries are labeled by region or as **Global**. We do not provide granular data for individual data centers.

If you select multiple regions or choose **All Regions** (Business and Enterprise Only), you may increase traffic to your servers. Each region sends individual health checks from three data centers.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/health-checks/","name":"Health Checks"}},{"@type":"ListItem","position":3,"item":{"@id":"/health-checks/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/health-checks/concepts/health-checks-regions/","name":"Health Checks regions"}}]}
```

---

---
title: Health Checks notifications
description: Set up notifications for Health Checks status changes.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Health Checks notifications

You can [configure notification emails](https://developers.cloudflare.com/health-checks/how-to/health-checks-notifications/#configure-notifications) to be alerted when the Health Check detects that there is a change in the status of your origin server. Cloudflare will send you an email within seconds so you can take the necessary action before customers are impacted.

The email provides information to determine what caused the health status change. You can evaluate when the change happened, the status of the origin server, if and why it is unhealthy, the expected response code, and the received response code.

## Configure notifications

1. In the Cloudflare dashboard, go to the **Health Checks** page.  
[ Go to **Health Checks** ](https://dash.cloudflare.com/?to=/:account/:zone/traffic/health-checks)
2. Select **Configure an alert**.
3. Fill out the **Notification name** and **Description**.
4. Add a Notification email.
5. Select **Next**.
6. Add health checks to include in your alerts.
7. Choose the **Notification trigger**, which determines when you receive alerts.
8. Select **Create**.

Note

A notification is only sent after a change of status in the majority of all selected region(s).

For a single region, this will be 2 of 3 data centers. With 13 regions selected, this will be 7 of 13 regions.

See [common error codes](https://developers.cloudflare.com/health-checks/health-checks-analytics/#common-error-codes) for more information regarding the cause of any changes to your Health Check.

Cloudflare encourages you to view your [Health Checks Analytics](https://developers.cloudflare.com/health-checks/health-checks-analytics/#common-error-codes) to get more context about the health of your servers over time.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/health-checks/","name":"Health Checks"}},{"@type":"ListItem","position":3,"item":{"@id":"/health-checks/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/health-checks/how-to/health-checks-notifications/","name":"Health Checks notifications"}}]}
```

---

---
title: Zone Lockdown
description: Restrict Health Checks access to specific Cloudflare IP addresses.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Zone Lockdown

Currently, any Cloudflare customer on a paid plan can configure Health Checks against any host or IP. [Zone Lockdown](https://developers.cloudflare.com/waf/tools/zone-lockdown/) specifies a list of one or more IP addresses, CIDR ranges, or networks that are the only IPs allowed to access a domain, subdomain, or URL. It allows multiple destinations in a single rule as well as IPv4 and IPv6 addresses. IP addresses not specified in the Zone Lockdown rule are denied access to the specified resources.

Customers who use zone lockdown and want their health checks to continue passing can use [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/create-dashboard/) to bypass zone lockdown.

## Bypass zone lockdown

To bypass zone lockdown using a WAF custom rule:

1. Follow the steps to [create a custom rule in the dashboard](https://developers.cloudflare.com/waf/custom-rules/create-dashboard/).
2. Create a custom rule matching on **user agent**.  
Cloudflare Health Checks have a user agent of the following format:`Mozilla/5.0 (compatible;Cloudflare-Healthchecks/1.0;+https://www.cloudflare.com/; healthcheck-id: XXX)` where `XXX` is replaced with the first 16 characters of the Health Check ID.  
To allow a specific Health Check, verify if the user agent contains the first 16 characters of the Health Check ID.
3. Set the action to _Skip_ and the corresponding feature to **Zone Lockdown** under **More components to skip**.

### Via the API

This example adds a new WAF custom rule to the ruleset with ID `{ruleset_id}` that skips zone lockdown for incoming requests with a user agent containing `1234567890abcdef`:

Terminal window

```

curl "https://api.cloudflare.com/client/v4/{zone_id}/rulesets/{ruleset_id}/rules" \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "action": "skip",

  "action_parameters": {

    "products": [

      "zoneLockdown"

    ]

  },

  "expression": "http.user_agent contains \"1234567890abcdef\"",

  "description": "bypass zone lockdown - specific healthcheck"

}'


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/health-checks/","name":"Health Checks"}},{"@type":"ListItem","position":3,"item":{"@id":"/health-checks/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/health-checks/how-to/zone-lockdown/","name":"Zone Lockdown"}}]}
```

---

---
title: Cloudflare Load Balancing
description: Distribute traffic across origin servers for availability and performance.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare Load Balancing

Maximize application performance and availability

 Paid add-on 

Cloudflare Load Balancing distributes traffic across your [endpoints](https://developers.cloudflare.com/glossary/?term=endpoint), which reduces endpoint strain and latency and improves the experience for end users.

Note

Enterprise customers can preview this product as a [non-contract service](https://developers.cloudflare.com/billing/understand/preview-services/), which provides full access, free of metered usage fees, limits, and certain other restrictions.

---

## Features

###  Load balancing and failover 

Distribute traffic evenly across your healthy endpoints, automatically failing over when an endpoint is unhealthy or unresponsive.

[ Use Load balancing and failover ](https://developers.cloudflare.com/load-balancing/load-balancers/) 

###  Active monitoring 

Monitor your endpoints at configurable intervals and across multiple data centers to look for specific status codes, response text, and timeouts.

[ Use Active monitoring ](https://developers.cloudflare.com/load-balancing/monitors/) 

###  Intelligent routing 

Choose whether to distribute requests based on endpoint latency, a visitor's geographic region, or even a visitor's GPS coordinates.

[ Use Intelligent routing ](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/) 

###  Custom rules 

Customize the behavior of your load balancer based on the characteristics of individual requests.

[ Use Custom rules ](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/) 

###  Analytics 

Review comprehensive analytics to evaluate traffic flow, assess endpoint health status, and review changes in pools and pool health over time.

[ Use Analytics ](https://developers.cloudflare.com/load-balancing/reference/load-balancing-analytics/) 

---

## Related products

**[Standalone Health Checks](https://developers.cloudflare.com/health-checks/)** 

Actively monitor whether your origin server is online by sending specific requests at regular intervals.

**[DNS](https://developers.cloudflare.com/dns/)** 

Get enterprise-grade authoritative DNS service with the fastest response time, unparalleled redundancy, and advanced security with built-in DDoS mitigation and DNSSEC.

**[Waiting Room](https://developers.cloudflare.com/waiting-room/)** 

Route excess users to a custom-branded waiting room, helping preserve customer experience and protect origin servers from being overwhelmed with requests.

---

## More resources

[Plans](https://www.cloudflare.com/plans/#overview) 

Compare available Cloudflare plans.

[Pricing](https://dash.cloudflare.com/?to=/:account/:zone/traffic/load-balancing/) 

Explore pricing options for Load Balancing in the dashboard.

[Reference Architecture](https://developers.cloudflare.com/reference-architecture/architectures/load-balancing/) 

Learn more about the structure of Cloudflare Load Balancers and their various configurations.

[Learning Paths](https://developers.cloudflare.com/learning-paths/) 

Module-based guidance on Cloudflare product workflows.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}}]}
```

---

---
title: Get started
description: Set up Cloudflare Load Balancing for your applications.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

Get started with load balancing in one of two ways:

* [Quickstart](https://developers.cloudflare.com/load-balancing/get-started/quickstart/): Get up and running quickly with Load Balancing.
* [Learning path](https://developers.cloudflare.com/learning-paths/load-balancing/concepts/): Check an in-depth walkthrough for how to plan and set up a load balancer.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/get-started/","name":"Get started"}}]}
```

---

---
title: Enable
description: Learn how to enable load balancing.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Enable

Load balancing is an add-on for your account, meaning your account needs a [billing profile](https://developers.cloudflare.com/billing/get-started/create-billing-profile/).

To enable [Load Balancing ↗](https://dash.cloudflare.com/?to=/:account/:zone/traffic/load-balancing):

1. In the Cloudflare dashboard, go to the **Load Balancing** page.  
[ Go to **Load Balancing** ](https://dash.cloudflare.com/?to=/:account/load-balancing)
2. Select **Enable Load Balancing** in the **Status** column.
3. Choose your plan options and confirm payment.

Note

Enterprise customers can preview this product as a [non-contract service](https://developers.cloudflare.com/billing/understand/preview-services/), which provides full access, free of metered usage fees, limits, and certain other restrictions.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/get-started/","name":"Get started"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/get-started/enable-load-balancing/","name":"Enable"}}]}
```

---

---
title: Concepts
description: Distribute traffic across servers with load balancing.
image: https://developers.cloudflare.com/cf-twitter-card.png
---

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

[Skip to content](#%5Ftop) 

# Concepts

Learn the concepts behind load balancing, whether you are using Cloudflare or another provider.

## Objectives

By the end of this module, you will be able to:

* Explain what load balancing is.
* Describe the differences between load balancers, pools, and servers.
* Explain what pool health is and how it affects load balancer traffic.
* List the different ways your traffic can be routed.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/learning-paths/","name":"Learning Paths"}},{"@type":"ListItem","position":3,"item":{"@id":"/learning-paths/load-balancing/concepts/","name":"Concepts"}}]}
```

---

---
title: Quickstart
description: Create a load balancer with pools and monitors in a few steps.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Quickstart

Get up and running quickly with Load Balancing. For more in-depth explanations, refer to the [Learning path](https://developers.cloudflare.com/learning-paths/load-balancing/concepts/).

This guide assumes you are familiar with the Cloudflare [Load Balancing components](https://developers.cloudflare.com/load-balancing/understand-basics/load-balancing-components/).

  
---

## Before you begin

Make sure you:

* Have access to multiple endpoints (origin servers, private or public IP addresses, virtual IP addresses (VIPs), etc), either physical or cloud-based.
* Have access to Load Balancing, available as an [add-on](https://developers.cloudflare.com/load-balancing/get-started/enable-load-balancing/) for any type of account.
* Have test and production hostnames that are covered by [SSL/TLS certificates](https://developers.cloudflare.com/load-balancing/load-balancers/dns-records/#ssltls-coverage).

## Create a monitor

A monitor issues health monitor requests at regular intervals to evaluate the health of each endpoint within a [pool](https://developers.cloudflare.com/load-balancing/pools/).

When a pool [becomes unhealthy](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/), your load balancer takes that pool out of the endpoint rotation.

* [ Dashboard ](#tab-panel-9158)
* [ API ](#tab-panel-9159)

**Set up the monitor**

You can create a monitor within the [load balancer workflow](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/) or in the **Monitors** tab:

1. Go to **Load Balancing**.
2. Select the **Monitors** tab.
3. Select **Create monitor**.
4. Add the following information:  
   * **Type**: The protocol to use for health monitors  
         * _Non-enterprise customers_: Choose **HTTP**, **HTTPS**, or **TCP**.  
         * _Enterprise customers_: Choose **HTTP**, **HTTPS**, **TCP**, **UDP ICMP**, **ICMP Ping**, or **SMTP**.  
   * **Path**: The endpoint path to run health monitor requests against  
   * **Port**: The destination port for health monitors
5. For additional settings, select **Advanced health monitor settings**:  
   * **Interval**:  
         * By increasing the default, you can improve failover time, but you may also increase load on your endpoints.  
         * Minimum time in seconds is 60 (Pro), 15 (Business), and 10 (Enterprise).  
   * **Timeout** and **Retries**:  
         * The health monitor request will return unhealthy if it exceeds the duration specified in **Timeout** (and exceeds this duration more times than the specified number of **Retries**).  
   * **Expected Code(s)**: The expected HTTP response codes listed individually (`200`, `302`) or as a range (for example, entering `2xx` would cover all response codes in the `200` range).  
   * **Response Body**:  
         * Looks for a case-insensitive substring in the response body.  
         * Make sure that the value is relatively static and within the first 10 KB of the HTML page.  
   * **Simulate Zone**:  
         * It is recommended to use the same zone in which the Load Balancer exists.  
         * Changes the egress zone settings of a health monitor request to ensure compatibility with features like [Authenticated Origin Pulls (mTLS)](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/), [Argo Smart Routing](https://developers.cloudflare.com/argo-smart-routing/), [Bring your own CA (mTLS)](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/), [Dedicated CDN Egress IPs](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/), and [HTTP/2 to Origin](https://developers.cloudflare.com/speed/optimization/protocol/http2-to-origin/).  
   * **Follow Redirects**:  
         * Instead of reporting a `301` or `302` code as unhealthy, the health monitor request follows redirects to the final endpoint.  
   * **Configure Request Header(s)**:  
         * Useful if your endpoints are expecting specific incoming headers.  
   * **Header**:  
         * The HTTP request headers to send in the health monitor. It is recommended that you set a Host header by default. The User-Agent header cannot be overridden. This parameter is only valid for HTTP and HTTPS monitors.
6. Select **Save**.

Note

To increase confidence in pool status, you can also increase the `consecutive_up` and `consecutive_down` fields when [creating a monitor with the API](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/methods/create/).

To become healthy or unhealthy, monitored endpoints must pass this health monitor request the consecutive number of times specified in these parameters.

**Prepare your servers**

Make sure that your firewall or web server does not block or rate limit your configured health monitors or requests associated with [Cloudflare IP addresses ↗](https://www.cloudflare.com/ips).

Each health monitor has the HTTP user-agent of `"Mozilla/5.0 (compatible; Cloudflare-Traffic-Manager/1.0; +https://www.cloudflare.com/traffic-manager/; pool-id: $poolid)"`, where the `$poolid` is the first 16 characters of the [associated pool](https://developers.cloudflare.com/load-balancing/pools/).

Warning

If you know that your endpoint is healthy but Load Balancing is reporting it as unhealthy, refer to our [Monitor troubleshooting guide](https://developers.cloudflare.com/load-balancing/troubleshooting/load-balancing-faq/#why-is-my-endpoint-or-pool-considered-unhealthy).

**Set up the monitor**

For a full list of monitor properties, refer to [Create Monitor](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/methods/create/). If you need help with API authentication, refer to [Cloudflare API documentation](https://developers.cloudflare.com/fundamentals/api/).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Load Balancing: Monitors and Pools Write`

Create Monitor

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/load_balancers/monitors" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "type": "https",

    "description": "Login page monitor",

    "method": "GET",

    "path": "/health",

    "header": {

        "Host": [

            "example.com"

        ],

        "X-App-ID": [

            "abc123"

        ]

    },

    "port": 8080,

    "timeout": 3,

    "retries": 0,

    "interval": 90,

    "expected_body": "alive",

    "expected_codes": "2xx",

    "follow_redirects": true,

    "allow_insecure": true,

    "consecutive_up": 3,

    "consecutive_down": 2,

    "probe_zone": "example.com"

  }'


```

The response contains the complete definition of the new monitor.

Response

```

{

  "success": true,

  "errors": [],

  "messages": [],

  "result": {

    "id": ":monitor-id",

    "created_on": "2021-01-01T05:20:00.12345Z",

    "modified_on": "2021-01-01T05:20:00.12345Z",

    "type": "https",

    "description": "Login page monitor",

    "method": "GET",

    "path": "/health",

    "header": {

      "Host": [

        "example.com"

      ],

      "X-App-ID": [

        "abc123"

      ]

    },

    "port": 8080,

    "timeout": 3,

    "retries": 0,

    "interval": 90,

    "expected_body": "alive",

    "expected_codes": "2xx",

    "follow_redirects": true,

    "allow_insecure": true,

    "consecutive_up": 3,

    "consecutive_down": 2,

    "probe_zone": "example.com"

  }

}


```

**Prepare your servers**

Make sure that your firewall or web server does not block or rate limit your configured health monitors or requests associated with [Cloudflare IP addresses ↗](https://www.cloudflare.com/ips).

Each health monitor has the HTTP user-agent of `"Mozilla/5.0 (compatible; Cloudflare-Traffic-Manager/1.0; +https://www.cloudflare.com/traffic-manager/; pool-id: $poolid)"`, where the `$poolid` is the first 16 characters of the [associated pool](https://developers.cloudflare.com/load-balancing/pools/).

Warning

If you know that your endpoint is healthy but Load Balancing is reporting it as unhealthy, refer to our [Monitor troubleshooting guide](https://developers.cloudflare.com/load-balancing/troubleshooting/load-balancing-faq/#why-is-my-endpoint-or-pool-considered-unhealthy).

Example monitor configuration

| Field            | Value     |
| ---------------- | --------- |
| Type             | HTTP      |
| Path             | /         |
| Port             | 80        |
| Interval         | 60        |
| Method           | GET       |
| Timeout          | 5 seconds |
| Retries          | 2         |
| Expected Code(s) | 200       |

## Create pools

Within Cloudflare, pools represent your endpoints and how they are organized. As such, a pool can be a group of several endpoints, or you could also have only one endpoint (an origin server, for example) per pool.

If you are familiar with DNS terminology, think of a pool as a “record set,” except Cloudflare only returns addresses that are considered healthy. You can attach health monitors to individual pools for customized monitoring. A pool can have either a single monitor or a monitor group attached — but not both.

* [ Dashboard ](#tab-panel-9162)
* [ API ](#tab-panel-9163)

You can create a pool within the [load balancer workflow](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/) or in the **Pools** tab:

1. Go to **Load Balancing**.
2. Select the **Pools** tab and then **Create pool**.
3. For your pool, enter the following information:  
   * A name (must be unique)  
   * A description to provide more detail on the name  
   * A choice for [**Endpoint Steering**](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/), which affects how your pool routes traffic to each endpoint
4. For each endpoint, enter the following information:  
   * A name (must be unique)  
   * The endpoint address or associated hostname  
   * (Optional) A [**Virtual Network**](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/private-net/cloudflared/tunnel-virtual-networks/). Required when the endpoint has a private IP address.  
   * A [**Weight**](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/#weights)  
   * (Optional) A [hostname](https://developers.cloudflare.com/load-balancing/additional-options/override-http-host-headers/) by clicking **Add host header**  
   * (Optional) The destination port to which the traffic will be served.

Note

If your endpoint is a website or application hosted on [Cloudflare Pages](https://developers.cloudflare.com/pages/), you will need to fill in the host header field with the project domain for it to resolve correctly.

1. Repeat this process for additional endpoints in the pool.
2. (Optional) Set up coordinates for [Proximity Steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/proximity-steering/) on the pool.
3. On the pool, update the following information:  
   * **Health Threshold**:  
   The Health Threshold is the number of healthy endpoints for the pool as a whole to be considered _Healthy_ and receive traffic based on pool order in a load balancer. Increasing this number makes the pool more reliable, but also more likely to become unhealthy.  
   * **Monitor**: Attach a [monitor](https://developers.cloudflare.com/load-balancing/monitors/create-monitor/)  
   * **Health Monitor Regions**: Choose whether to check pool health from [multiple locations](https://developers.cloudflare.com/load-balancing/monitors/#health-monitor-regions), which increases accuracy but can lead to probe traffic to your endpoint  
   * **Pool Notifications**: You can set up new alerts - and view existing alerts - to be notified when pools are enabled or disabled, or pools or endpoints have changes in their [health status](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/).
4. When finished, select **Save**.

For a full list of properties, refer to [Create Pool](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/create/). If you need help with API authentication, refer to [Cloudflare API documentation](https://developers.cloudflare.com/fundamentals/api/).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Load Balancing: Monitors and Pools Write`

Create Pool

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/load_balancers/pools" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "description": "Primary data center - Provider XYZ",

    "name": "primary-dc-1",

    "enabled": false,

    "load_shedding": {

        "default_percent": 0,

        "default_policy": "random",

        "session_percent": 0,

        "session_policy": "hash"

    },

    "minimum_origins": 2,

    "monitor": "f1aba936b94213e5b8dca0c0dbf1f9cc",

    "check_regions": [

        "WEU",

        "ENAM"

    ],

    "origins": [

        {

            "name": "app-server-1",

            "address": "0.0.0.0",

            "enabled": true,

            "weight": 0.56,

            "header": {

                "Host": [

                    "example.com"

                ]

            }

        }

    ],

    "origin_steering": {

        "policy": "random"

    },

    "notification_filter": {

        "origin": {

            "disable": false,

            "healthy": null

        },

        "pool": {

            "disable": false,

            "healthy": null

        }

    }

  }'


```

The response contains the complete definition of the new pool.

Response

```

{

  "success": true,

  "errors": [],

  "messages": [],

  "result": {

    "id": "17b5962d775c646f3f9725cbc7a53df4",

    "created_on": "2021-01-01T05:20:00.12345Z",

    "modified_on": "2021-01-01T05:20:00.12345Z",

    "description": "Primary data center - Provider XYZ",

    "name": "primary-dc-1",

    "enabled": false,

    "load_shedding": {

      "default_percent": 0,

      "default_policy": "random",

      "session_percent": 0,

      "session_policy": "hash"

    },

    "minimum_origins": 2,

    "monitor": "f1aba936b94213e5b8dca0c0dbf1f9cc",

    "check_regions": [

      "WEU",

      "ENAM"

    ],

    "origins": [

      {

        "name": "app-server-1",

        "address": "0.0.0.0",

        "enabled": true,

        "weight": 0.56,

        "header": {

          "Host": [

            "example.com"

          ]

        }

      }

    ],

    "origin_steering": {

      "policy": "random"

    },

    "notification_filter": {

      "origin": {

        "disable": false,

        "healthy": null

      },

      "pool": {

        "disable": false,

        "healthy": null

      }

    }

  }

}


```

After creating the pool, you would also want to [create a new notification](https://developers.cloudflare.com/api/resources/alerting/subresources/policies/methods/create/) with the following parameters specified:

```

"alert_type": "load_balancing_health_alert",

"filters": {

  "pool_id": <<ARRAY_OF_INCLUDED_POOL_IDS>>,

  "new_health": <<ARRAY_OF_STATUS_TRIGGERS>> ["Unhealthy", "Healthy"],

  "event_source": <<ARRAY_OF_OBJECTS_WATCHED>> ["pool", "origin"]

}


```

## Confirm pool health

Before directing any traffic to your pools, make sure that your pools and monitors are set up correctly. The status of your health check will be _unknown_ until the results of the first check are available.

* [ Dashboard ](#tab-panel-9156)
* [ API ](#tab-panel-9157)

To confirm pool health using the dashboard:

1. Go to **Load Balancing**.
2. Select the **Pools** tab.
3. For pools and individual endpoints, review the values in the **Health** and **Endpoint Health** columns.

For more information on pool and endpoint health statuses, refer to [How a pool becomes unhealthy](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/#how-a-pool-becomes-unhealthy).

To fetch the latest health status of all pools, use the [List Pools](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/list/) command, paying attention to the `healthy` value for pools and origins (endpoints).

For troubleshooting a specific pool's health, use the [Pool Health Details](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/subresources/health/methods/get/) command.

### Unexpected health status

If you notice that healthy pools are being marked unhealthy:

* Review [how endpoints and pools become unhealthy](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/).
* Refer to the [Troubleshooting section](https://developers.cloudflare.com/load-balancing/troubleshooting/).

## Create a load balancer on a test subdomain

Instead of starting on your production domain, you likely should create a load balancer on a test or staging domain. This may involve temporary changes to your monitors and pools, depending on your infrastructure setup.

Starting with a test domain allows you to verify everything is working correctly before routing production traffic.

* [ Dashboard ](#tab-panel-9160)
* [ API ](#tab-panel-9161)

To create a Public or a Private load balancer in the dashboard:

### Create a Public load balancer

1. Go to **Load Balancing** and select **Create load balancer**.
2. On the **Load Balancer Setup**, select **Public load balancer**
3. Choose the website to which you want to add this load balancer.
4. On the **Hostname** page:  
   * Enter a **Hostname**, which is the DNS name at which the load balancer is available. For more details on record priority, refer to [DNS records for load balancing](https://developers.cloudflare.com/load-balancing/load-balancers/dns-records/).  
   * From the **Data Localization** dropdown, select the [region](https://developers.cloudflare.com/data-localization/how-to/load-balancing/#regional-services) you would like to use on your domain.  
   * Toggle the orange cloud icon to update the [proxy mode](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/), which affects how traffic is routed and which IP addresses are advertised.  
   * Add a description for your load balancer.  
   * If you want [session-based load balancing](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/), toggle the **Session Affinity** switch.  
   * If you want [Adaptive Routing](https://developers.cloudflare.com/load-balancing/understand-basics/adaptive-routing/), toggle the **Adaptive Routing** switch.
5. Select **Next**.
6. On the **Add a Pool** page:  
   * Select one or more existing pools or [create a new pool](https://developers.cloudflare.com/load-balancing/pools/create-pool/#create-a-pool).  
   * If you are going to set [traffic steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/standard-options/) to **Off**, re-order the pools in your load balancer to adjust the fallback order.  
   * If needed, update the [**Fallback Pool**](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/#fallback-pools).  
   * If you choose to set traffic steering to **Random**, you can set [Weights](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/standard-options/#random-steering) (via the API) to your pools to determine the percentage of traffic sent to each pool.
7. Select **Next**.
8. On the **Monitors** page:  
   * Review the monitors attached to your pools.  
   * If needed, you can attach an existing monitor or [create a new monitor](https://developers.cloudflare.com/load-balancing/monitors/create-monitor/#create-a-monitor).
9. Select **Next**.
10. On the **Traffic Steering** page, choose an option for [Traffic steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/) and select **Next**.
11. On the **Custom Rules** page, select an existing rule or [create a new rule](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/).
12. Select **Next**.
13. On the **Review** page:  
   * Review your configuration and make any changes.  
   * Choose whether to **Save as Draft** or **Save and Deploy**.

### Create a Private load balancer

1. Go to **Load Balancing** and select **Create load balancer**.
2. On the **Load Balancer Setup**, select **Private load balancer**
3. Associate your load balancer with either a Cloudflare private IP or a specified IP address and create a description for your load balancer.
4. On the **Add a Pool** page:  
   * Select one or more existing pools or [create a new pool](https://developers.cloudflare.com/load-balancing/pools/create-pool/#create-a-pool).  
   * If you are going to set [traffic steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/standard-options/) to **Off**, re-order the pools in your load balancer to adjust the fallback order.  
   * If needed, update the [**Fallback Pool**](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/#fallback-pools).  
   * If you choose to set traffic steering to **Random**, you can set [Weights](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/standard-options/#random-steering) (via the API) to your pools to determine the percentage of traffic sent to each pool.
5. Select **Next**.
6. On the **Monitors** page:  
   * Review the monitors attached to your pools.  
   * If needed, you can attach an existing monitor or [create a new monitor](https://developers.cloudflare.com/load-balancing/monitors/create-monitor/#create-a-monitor).
7. Select **Next**.
8. On the **Traffic Steering** page, choose an option for [Traffic steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/) and select **Next**.
9. Select **Next**.
10. On the **Review** page:  
   * Review your configuration and make any changes.  
   * Choose whether to **Save as Draft** or **Save and Deploy**.

For a full list of properties, refer to [Create Load Balancer](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/create/). If you need help with API authentication, refer to [Cloudflare API documentation](https://developers.cloudflare.com/fundamentals/api/).

Note

Since load balancers only exist on a zone — and not an account — you may need to get the zone `id` with the [List Zones](https://developers.cloudflare.com/api/resources/zones/methods/list/) command.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Load Balancers Write`

Create Load Balancer

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/load_balancers" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "description": "Load Balancer for lb.example.com",

    "name": "lb.example.com",

    "enabled": true,

    "ttl": 30,

    "fallback_pool": "17b5962d775c646f3f9725cbc7a53df4",

    "default_pools": [

        "17b5962d775c646f3f9725cbc7a53df4",

        "9290f38c5d07c2e2f4df57b1f61d4196",

        "00920f38ce07c2e2f4df50b1f61d4194"

    ],

    "proxied": true,

    "steering_policy": "random_steering",

    "session_affinity": "cookie",

    "session_affinity_attributes": {

        "samesite": "Auto",

        "secure": "Auto",

        "drain_duration": 100,

        "zero_downtime_failover": "sticky"

    },

    "session_affinity_ttl": 5000,

    "adaptive_routing": {

        "failover_across_pools": true

    },

    "location_strategy": {

        "prefer_ecs": "always",

        "mode": "resolver_ip"

    },

    "random_steering": {

        "pool_weights": {

            "de90f38ced07c2e2f4df50b1f61d4194": 0.3,

            "9290f38c5d07c2e2f4df57b1f61d4196": 0.5

        },

        "default_weight": 0.2

    }

  }'


```

The response contains the complete definition of the new load balancer.

Response

```

{

  "success": true,

  "errors": [],

  "messages": [],

  "result": {

    "id": "699d98642c564d2e855e9661899b7252",

    "created_on": "2021-01-01T05:20:00.12345Z",

    "modified_on": "2021-01-01T05:20:00.12345Z",

    "description": "Load Balancer for lb.example.com",

    "name": "lb.example.com",

    "enabled": true,

    "ttl": 30,

    "fallback_pool": "17b5962d775c646f3f9725cbc7a53df4",

    "default_pools": [

      "17b5962d775c646f3f9725cbc7a53df4",

      "9290f38c5d07c2e2f4df57b1f61d4196",

      "00920f38ce07c2e2f4df50b1f61d4194"

    ],

    "proxied": true,

    "steering_policy": "random_steering",

    "session_affinity": "cookie",

    "session_affinity_attributes": {

      "samesite": "Auto",

      "secure": "Auto",

      "drain_duration": 100,

      "zero_downtime_failover": "sticky"

    },

    "session_affinity_ttl": 5000,

    "random_steering": {

      "pool_weights": {

        "de90f38ced07c2e2f4df50b1f61d4194": 0.3,

        "9290f38c5d07c2e2f4df57b1f61d4196": 0.5

      },

      "default_weight": 0.2

    }

  }

}


```

## Optional - Review load balancing analytics

As you send sample requests to your test domain, review the [load balancing analytics](https://developers.cloudflare.com/load-balancing/reference/load-balancing-analytics/) page to make sure your load balancer is distributing requests like you were expecting.

## Route production traffic

Now that you have set up your load balancer and verified everything is working correctly, you can put the load balancer on a live domain or subdomain:

1. If you update your pools and monitors, review the pool health again to make sure everything is working as expected.
2. Confirm that your production hostname has the correct [priority order](https://developers.cloudflare.com/load-balancing/load-balancers/dns-records/#priority-order) of DNS records and is covered by an [SSL/TLS certificate](https://developers.cloudflare.com/load-balancing/load-balancers/dns-records/#ssltls-coverage).
3. Configure your load balancer to receive production traffic, which could involve either:  
   * Editing the **Hostname** of your existing load balancer.  
   * Updating the `CNAME` record sending traffic to your load balancer.

Note

If you have an Enterprise account, also evaluate your application for any excluded paths. For example, you might not want the load balancer to distribute requests directed at your `/admin` path. For any exceptions, set up an [origin rule](https://developers.cloudflare.com/rules/origin-rules/features/#dns-record).

## Optional - Next steps

Your load balancer should be receiving production traffic (and you can confirm this by reviewing the [analytics](https://developers.cloudflare.com/load-balancing/reference/load-balancing-analytics/)).

Though your product is officially set up, you may want to consider the following suggestions.

### Usage-based notifications

Since this is a service with [usage-based billing](https://developers.cloudflare.com/billing/understand/usage-based-billing/), Cloudflare recommends that you set up usage-based billing notifications to avoid unexpected bills.

To set up those notifications:

1. In the Cloudflare dashboard, go to the **Notifications** page.  
[ Go to **Notifications** ](https://dash.cloudflare.com/?to=/:account/notifications)
2. On **Alert Type** of **Usage Based Billing**, click **Select**.
3. Fill out the following information:  
   * **Name**  
   * **Product**  
   * **Notification limit** (exact metric will vary based on product)  
   * **Notification email**  
Note  
Some plans also have access to alerts through [PagerDuty](https://developers.cloudflare.com/notifications/get-started/configure-pagerduty/) and [Webhooks](https://developers.cloudflare.com/notifications/get-started/configure-webhooks/).
4. Select **Save**.

### Additional configuration options

You may want to further customize how your load balancer routes traffic or integrate your load balancer with other Cloudflare products:

* [ Additional DNS records ](https://developers.cloudflare.com/load-balancing/additional-options/additional-dns-records/)
* [ Cloudflare Tunnel (published applications) ](https://developers.cloudflare.com/load-balancing/additional-options/cloudflare-tunnel/)
* [ Spectrum ](https://developers.cloudflare.com/load-balancing/additional-options/spectrum/)
* [ Perform planned maintenance ](https://developers.cloudflare.com/load-balancing/additional-options/planned-maintenance/)
* [ Load shedding ](https://developers.cloudflare.com/load-balancing/additional-options/load-shedding/)
* [ DNS persistence ](https://developers.cloudflare.com/load-balancing/additional-options/dns-persistence/)
* [ Load Balancing with the China Network ](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-china/)
* [ Override HTTP Host headers ](https://developers.cloudflare.com/load-balancing/additional-options/override-http-host-headers/)
* [ Custom load balancing rules ](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/)
* [ Integrate with PagerDuty ](https://developers.cloudflare.com/load-balancing/additional-options/pagerduty-integration/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/get-started/","name":"Get started"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/get-started/quickstart/","name":"Quickstart"}}]}
```

---

---
title: Load balancers
description: Configure load balancers to distribute traffic across pools.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Load balancers

A load balancer distributes traffic among pools according to [pool health](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/) and [traffic steering policies](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/). Each load balancer is identified by its DNS hostname (`lb.example.com`, `dev.example.com`, etc.) or IP address.

Note

For an overview of how the Cloudflare Load Balancing solution works, refer to [Load Balancing components](https://developers.cloudflare.com/load-balancing/understand-basics/load-balancing-components/). For more background information on what load balancers are, refer to the Cloudflare [Learning Center ↗](https://www.cloudflare.com/learning/performance/what-is-load-balancing/).

---

## Common configurations

For suggestions, refer to [Common load balancer configurations](https://developers.cloudflare.com/load-balancing/load-balancers/common-configurations/).

## Public vs. Private Load Balancers

Public Load Balancers are designed to handle traffic from the public Internet. When deployed, they automatically receive a hostname, making them immediately accessible. These load balancers can direct traffic to a range of destinations, including public hostnames, public IP addresses, and private IP addresses.

Private Load Balancers, in contrast, are meant for internal use within private networks. They do not automatically receive a hostname, but one can be assigned via Gateway Firewall Policies or through an internal DNS system. Private Load Balancers only accept traffic over a private network on-ramp, such as [the Cloudflare One Client](https://developers.cloudflare.com/warp-client/) or [Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/). They are capable of forwarding traffic exclusively to private IP addresses.

## Load balancing and existing DNS records

For details about DNS records, refer to [DNS records for load balancing](https://developers.cloudflare.com/load-balancing/load-balancers/dns-records/).

## HTTP keep-alive (persistent HTTP connection)

Cloudflare maintains keep-alive connections to improve performance and reduce cost of recurring TCP connects in the request transaction as Cloudflare proxies customer traffic from its edge network to the site's origin.

Ensure HTTP Keep-Alive connections are enabled on your origin. Cloudflare reuses open TCP connections for up to 15 minutes (900 seconds) after the last HTTP request. Origin web servers close TCP connections if too many are open. HTTP Keep-Alive helps avoid premature reset of connections for requests proxied by Cloudflare.

### Session cookies

**When using HTTP cookies to track and bind user sessions to a specific server**, configure [Session Affinity](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/) to parse HTTP requests by cookie header. Doing so directs each request to the correct application server even when HTTP requests share the same TCP connection due to keep-alive.

**For example, F5 BIG-IP load balancers set a session cookie at the beginning of a TCP connection** (if none exists) and then ignore all cookies from subsequent HTTP requests on the same TCP connection. This tends to break session affinity because Cloudflare sends multiple HTTP sessions on the same TCP connection. Configuring the load balancer to parse HTTP requests by cookie headers avoids this issue.

---

## Create load balancers

For step-by-step guidance, refer to [Create a load balancer](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/).

---

## Properties

For an up-to-date list of load balancer properties, refer to [Load balancer properties](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/get/) in the Cloudflare API documentation.

---

## API commands

The Cloudflare API supports the following commands for load balancers.

| Command                                                                                                            | Method | Endpoint                             |
| ------------------------------------------------------------------------------------------------------------------ | ------ | ------------------------------------ |
| [Create Load Balancer](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/create/)           | POST   | /zones/:zone\_id/load\_balancers     |
| [Delete Load Balancer](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/delete/)           | DELETE | /zones/:zone\_id/load\_balancers/:id |
| [List Load Balancers](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/list/)              | GET    | /zones/:zone\_id/load\_balancers     |
| [Load Balancer Details](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/get/)             | GET    | /zones/:zone\_id/load\_balancers/:id |
| [Overwrite specific properties](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/edit/)    | PATCH  | /zones/:zone\_id/load\_balancers/:id |
| [Overwrite entire Load Balancer](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/update/) | PUT    | /zones/:zone\_id/load\_balancers/:id |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/load-balancers/","name":"Load balancers"}}]}
```

---

---
title: Common configurations
description: Common load balancer configurations for active-active and failover.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Common configurations

Consider the following sections to understand how to achieve some commonly used load balancer configurations.

This page assumes you understand the Cloudflare [Load Balancing components](https://developers.cloudflare.com/load-balancing/understand-basics/load-balancing-components/) and how to create and edit each of them.

## Active - Passive Failover

An **active-passive failover** sends traffic to the endpoints in your active pool until a failure threshold (configurable) is reached. At the point of failure, your load balancer then redirects traffic to the passive pool.

This setup ensures uninterrupted service and helps with planned outages, but it might lead to slower traffic overall.

To set up a load balancer with **active-passive failover**:

1. Create a load balancer with two pools (`primary` and `secondary`).
2. In the list of pools, set the following order:  
   1. `primary`  
   2. `secondary`
3. For **Traffic Steering**, select [**Off**](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/standard-options/#off---failover).

With this setup, your load balancer will direct all traffic to `primary` until `primary` has fewer available endpoints than specified in its **Health Threshold**. Only then will your load balancer direct traffic to `secondary`.

In the event that all pools are marked down, Cloudflare uses the **fallback pool**, which is the option of last resort for successfully sending traffic to an endpoint. Since the fallback pool is a last resort, its health is not taken into account, and Cloudflare reports its status as **No Health**. You can select the fallback pool via the API or in the Cloudflare dashboard. For more on working with fallback pools, refer to [Pool-level steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/).

## Active - Active Failover

An **active-active failover** distributes traffic to endpoints in the same pool until the pool reaches its failure threshold (configurable). At the point of failure, your load balancer would then re-direct traffic to the **fallback pool**.

This setup speeds up overall requests, but is more vulnerable to planned or unplanned outages.

To set up a load balancer with **active-active failover**, either:

* Create a load balancer with a single pool (`primary`) with multiple endpoints (`endpoint-1` and `endpoint-2`) and set the same [**Weight**](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/#weights) for each endpoint.
* Create a load balancer with two pools (`primary` and `secondary`) and — for [**Traffic Steering**](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/) — select any option except for **Off**.

Note

For more background reading on server failover and common configurations, refer to [our Learning Center ↗](https://www.cloudflare.com/learning/performance/what-is-server-failover/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/load-balancers/","name":"Load balancers"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/load-balancers/common-configurations/","name":"Common configurations"}}]}
```

---

---
title: Manage load balancers
description: Learn how to set up and maintain load balancers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Manage load balancers

A load balancer distributes traffic among pools according to [pool health](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/) and [traffic steering policies](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/). Each load balancer is identified by its DNS hostname (`lb.example.com`, `dev.example.com`, etc.) or IP address.

  
For more details about load balancers, refer to [Load balancers](https://developers.cloudflare.com/load-balancing/load-balancers/).

## Create a load balancer

* [ Dashboard ](#tab-panel-9168)
* [ API ](#tab-panel-9169)

To create a Public or a Private load balancer in the dashboard:

### Create a Public load balancer

1. Go to **Load Balancing** and select **Create load balancer**.
2. On the **Load Balancer Setup**, select **Public load balancer**
3. Choose the website to which you want to add this load balancer.
4. On the **Hostname** page:  
   * Enter a **Hostname**, which is the DNS name at which the load balancer is available. For more details on record priority, refer to [DNS records for load balancing](https://developers.cloudflare.com/load-balancing/load-balancers/dns-records/).  
   * From the **Data Localization** dropdown, select the [region](https://developers.cloudflare.com/data-localization/how-to/load-balancing/#regional-services) you would like to use on your domain.  
   * Toggle the orange cloud icon to update the [proxy mode](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/), which affects how traffic is routed and which IP addresses are advertised.  
   * Add a description for your load balancer.  
   * If you want [session-based load balancing](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/), toggle the **Session Affinity** switch.  
   * If you want [Adaptive Routing](https://developers.cloudflare.com/load-balancing/understand-basics/adaptive-routing/), toggle the **Adaptive Routing** switch.
5. Select **Next**.
6. On the **Add a Pool** page:  
   * Select one or more existing pools or [create a new pool](https://developers.cloudflare.com/load-balancing/pools/create-pool/#create-a-pool).  
   * If you are going to set [traffic steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/standard-options/) to **Off**, re-order the pools in your load balancer to adjust the fallback order.  
   * If needed, update the [**Fallback Pool**](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/#fallback-pools).  
   * If you choose to set traffic steering to **Random**, you can set [Weights](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/standard-options/#random-steering) (via the API) to your pools to determine the percentage of traffic sent to each pool.
7. Select **Next**.
8. On the **Monitors** page:  
   * Review the monitors attached to your pools.  
   * If needed, you can attach an existing monitor or [create a new monitor](https://developers.cloudflare.com/load-balancing/monitors/create-monitor/#create-a-monitor).
9. Select **Next**.
10. On the **Traffic Steering** page, choose an option for [Traffic steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/) and select **Next**.
11. On the **Custom Rules** page, select an existing rule or [create a new rule](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/).
12. Select **Next**.
13. On the **Review** page:  
   * Review your configuration and make any changes.  
   * Choose whether to **Save as Draft** or **Save and Deploy**.

### Create a Private load balancer

1. Go to **Load Balancing** and select **Create load balancer**.
2. On the **Load Balancer Setup**, select **Private load balancer**
3. Associate your load balancer with either a Cloudflare private IP or a specified IP address and create a description for your load balancer.
4. On the **Add a Pool** page:  
   * Select one or more existing pools or [create a new pool](https://developers.cloudflare.com/load-balancing/pools/create-pool/#create-a-pool).  
   * If you are going to set [traffic steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/standard-options/) to **Off**, re-order the pools in your load balancer to adjust the fallback order.  
   * If needed, update the [**Fallback Pool**](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/#fallback-pools).  
   * If you choose to set traffic steering to **Random**, you can set [Weights](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/standard-options/#random-steering) (via the API) to your pools to determine the percentage of traffic sent to each pool.
5. Select **Next**.
6. On the **Monitors** page:  
   * Review the monitors attached to your pools.  
   * If needed, you can attach an existing monitor or [create a new monitor](https://developers.cloudflare.com/load-balancing/monitors/create-monitor/#create-a-monitor).
7. Select **Next**.
8. On the **Traffic Steering** page, choose an option for [Traffic steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/) and select **Next**.
9. Select **Next**.
10. On the **Review** page:  
   * Review your configuration and make any changes.  
   * Choose whether to **Save as Draft** or **Save and Deploy**.

For a full list of properties, refer to [Create Load Balancer](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/create/). If you need help with API authentication, refer to [Cloudflare API documentation](https://developers.cloudflare.com/fundamentals/api/).

Note

Since load balancers only exist on a zone — and not an account — you may need to get the zone `id` with the [List Zones](https://developers.cloudflare.com/api/resources/zones/methods/list/) command.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Load Balancers Write`

Create Load Balancer

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/load_balancers" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "description": "Load Balancer for lb.example.com",

    "name": "lb.example.com",

    "enabled": true,

    "ttl": 30,

    "fallback_pool": "17b5962d775c646f3f9725cbc7a53df4",

    "default_pools": [

        "17b5962d775c646f3f9725cbc7a53df4",

        "9290f38c5d07c2e2f4df57b1f61d4196",

        "00920f38ce07c2e2f4df50b1f61d4194"

    ],

    "proxied": true,

    "steering_policy": "random_steering",

    "session_affinity": "cookie",

    "session_affinity_attributes": {

        "samesite": "Auto",

        "secure": "Auto",

        "drain_duration": 100,

        "zero_downtime_failover": "sticky"

    },

    "session_affinity_ttl": 5000,

    "adaptive_routing": {

        "failover_across_pools": true

    },

    "location_strategy": {

        "prefer_ecs": "always",

        "mode": "resolver_ip"

    },

    "random_steering": {

        "pool_weights": {

            "de90f38ced07c2e2f4df50b1f61d4194": 0.3,

            "9290f38c5d07c2e2f4df57b1f61d4196": 0.5

        },

        "default_weight": 0.2

    }

  }'


```

The response contains the complete definition of the new load balancer.

Response

```

{

  "success": true,

  "errors": [],

  "messages": [],

  "result": {

    "id": "699d98642c564d2e855e9661899b7252",

    "created_on": "2021-01-01T05:20:00.12345Z",

    "modified_on": "2021-01-01T05:20:00.12345Z",

    "description": "Load Balancer for lb.example.com",

    "name": "lb.example.com",

    "enabled": true,

    "ttl": 30,

    "fallback_pool": "17b5962d775c646f3f9725cbc7a53df4",

    "default_pools": [

      "17b5962d775c646f3f9725cbc7a53df4",

      "9290f38c5d07c2e2f4df57b1f61d4196",

      "00920f38ce07c2e2f4df50b1f61d4194"

    ],

    "proxied": true,

    "steering_policy": "random_steering",

    "session_affinity": "cookie",

    "session_affinity_attributes": {

      "samesite": "Auto",

      "secure": "Auto",

      "drain_duration": 100,

      "zero_downtime_failover": "sticky"

    },

    "session_affinity_ttl": 5000,

    "random_steering": {

      "pool_weights": {

        "de90f38ced07c2e2f4df50b1f61d4194": 0.3,

        "9290f38c5d07c2e2f4df57b1f61d4196": 0.5

      },

      "default_weight": 0.2

    }

  }

}


```

### Sharing your load balancer with other sites

You can share your load balancer with other sites in your account by [creating a canonical name (CNAME) record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/). This is useful for sharing configurations with multiple other domains so you do not have to create new load balancers for each site.

You can also configure separate load balancers for each domain and reuse monitors and pools. This is especially useful for changing the failover order for different domains, such as when your `example.co.uk` server has a different failover priority from `example.com` or `example.com.au`.

Note

Sharing load balancers across sites is only supported if the target zone is on a [full DNS setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/). It is not supported if the target zone is on a `CNAME` setup.

---

## Edit a load balancer

* [ Dashboard ](#tab-panel-9164)
* [ API ](#tab-panel-9165)

To edit a load balancer in the dashboard:

1. Go to **Load Balancing**.
2. On a specific load balancer, select **Edit**.
3. While going through the [creation workflow](#create-a-load-balancer), update settings as needed.
4. On the **Review** step, select **Save**.

When you edit a load balancer with the API, your request type depends on how much you want to edit.

To update specific settings without having to resubmit the entire configuration, use a [PATCH](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/edit/) request. For broader changes, use a [PUT](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/update/) request.

---

## Delete a load balancer

If you delete or disable a load balancer, your endpoint's response to requests will depend on your [existing DNS records](https://developers.cloudflare.com/load-balancing/load-balancers/dns-records/#disabling-a-load-balancer).

* [ Dashboard ](#tab-panel-9166)
* [ API ](#tab-panel-9167)

To delete a load balancer in the dashboard:

1. Go to **Load Balancing**.
2. On a specific load balancer, click **Delete**.

To delete a load balancer using the API, send a [DELETE](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/delete/) request.

---

## Set up alerts

You can configure alerts to receive notifications for changes in the health status of your pools or endpoints.

Load Balancing Health Alert

**Who is it for?**

Customers who want to be warned about [changes in health status](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/) in their pools or origins.

**Other options / filters**

Available filters include:

* You can search for and add pools from your list of pools, as well as **Include future pools** (if all pools are selected).
* You can choose the trigger that fires the notification when the health status becomes **unhealthy**, **healthy**, or **either unhealthy or healthy**
* You can choose the trigger that fires the notification when the event source health status changes in **pool**, **origin**, or **either pool or origin**.
**Included with**

Purchase of [Load Balancing](https://developers.cloudflare.com/load-balancing/get-started/enable-load-balancing/).

**What should you do if you receive one?**

Evaluate [load balancing analytics](https://developers.cloudflare.com/load-balancing/reference/load-balancing-analytics/) to review changes in health status over time.

Refer to [Cloudflare Notifications](https://developers.cloudflare.com/notifications/get-started/) for more information on how to set up an alert.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/load-balancers/","name":"Load balancers"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/load-balancers/create-load-balancer/","name":"Manage load balancers"}}]}
```

---

---
title: DNS records
description: DNS records created for load balanced hostnames.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNS records

When you [create a load balancer](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/), Cloudflare automatically creates an LB DNS record for the specified **Hostname**. This functionality allows you to use a hostname with or without an existing DNS record. Private load balancers do not receive an automatic DNS record. Instead, you can configure a hostname using your internal DNS system or by applying a [Gateway Firewall override](https://developers.cloudflare.com/cloudflare-one/traffic-policies/dns-policies/#override) to a hostname.

## Supported records

For customers on non-Enterprise plans, Cloudflare supports load balancing for `A`, `AAAA`, and `CNAME` records.

For customers on Enterprise plans, Cloudflare supports load balancing for `A`, `AAAA`, `CNAME`, **MX**, and **SRV** records.

## Priority order

For hostnames with existing DNS records, the LB record takes precedence when it is more or equally specific:

* **Scenario 1**:  
   * **A, AAAA, or CNAME**: `x.example.com`  
   * **LB record**: `x.example.com`  
   * **Outcome**: LB record takes precedence because it is as specific as the DNS record.
* **Scenario 2**:  
   * **A, AAAA, or CNAME**: `y.example.com`  
   * **LB record**: `*.example.com` (wildcard record)  
   * **Outcome**: DNS record takes precedence because it is more specific.
* **Scenario 3**:  
   * **A, AAAA, or CNAME**: `*.example.com`  
   * **LB record**: `*.example.com`  
   * **Outcome**: LB record takes precedence because it is as specific as the DNS record.

Note

This behavior only applies to [supported records](#supported-records) (determined by your plan type).

If the DNS record points to a [SaaS provider](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) and an active [custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/) exists, the custom hostname will take precedence over the Load Balancing record:

* **Scenario 4**:  
   * **CNAME**: `x.example.com` with target to a Cloudflare for SaaS provider  
   * **LB record**: `x.example.com`  
   * **Active custom hostname on the SaaS provider side**: `x.example.com`  
   * **Outcome**: Custom hostname takes precedence.

## Disabling a load balancer

When you disable a load balancer, requests to a specific hostname depend on your existing DNS records:

* If you have existing DNS records, these records will be served.
* If there are no existing records, requests to the hostname will fail.

In both cases, disabling your load balancer prevents traffic from going to any associated endpoint or fallback pools.

If you already have an existing `A`, `AAAA`, or `CNAME` record, be aware that the change may take some time to propagate due to [Time to Live (TTL)](https://developers.cloudflare.com/dns/manage-dns-records/reference/ttl/) and any record changes is affected, as your local DNS cache may take longer to update.

## SSL/TLS coverage

Due to internal limitations, on [Partial (CNAME) setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/) the Cloudflare [Universal SSL certificates](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) do not cover load balancing hostnames by default. This behavior will be corrected in the future.

As a current workaround for a domain or first-level subdomain (`lb.example.com`), create a [proxied CNAME/A/AAAA record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) for that hostname.

For example, if your load balancer hostname was `lb.example.com`, you could create the following record solely for the purpose of SSL/TLS coverage.

| Type | Name | IPv4 address | Proxy status |
| ---- | ---- | ------------ | ------------ |
| A    | lb   | 192.0.2.1    | Proxied      |

Based on the [priority order](#priority-order), it would not receive any traffic because it is as equally specific as the LB hostname.

To get coverage for any deeper subdomain (`lb.dev.example.com`), purchase an [advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/load-balancers/","name":"Load balancers"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/load-balancers/dns-records/","name":"DNS records"}}]}
```

---

---
title: Pools
description: Pools of origin servers for load balancing traffic distribution.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Pools

Within Cloudflare, pools represent your endpoints and how they are organized. As such, a pool can be a group of several endpoints, or you could also have only one endpoint (an origin server, for example) per pool.

If you are familiar with DNS terminology, think of a pool as a “record set,” except Cloudflare only returns addresses that are considered healthy. You can attach health monitors to individual pools for customized monitoring. A pool can have either a single monitor or a monitor group attached — but not both.

For more details about how endpoints and pools become unhealthy, refer to [Endpoint and pool health](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/).

Warning

Since load balancing targets are not limited to origin web servers, the term `endpoints` has been introduced. Refer to [Service-Specific Terms ↗](https://www.cloudflare.com/service-specific-terms-other-terms/) for its use in the context of Cloudflare offerings, and to [load balancing concepts](https://developers.cloudflare.com/load-balancing/understand-basics/load-balancing-components/) or [Reference Architecture](https://developers.cloudflare.com/reference-architecture/architectures/load-balancing/) for use case examples.

On the [Load Balancing API](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/get/), `origin` has been maintained.

---

## Properties

For an up-to-date list of pool properties, refer to [Pool properties](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/list/) in our API documentation.

---

## Create pools

For step-by-step guidance, refer to [Create pools](https://developers.cloudflare.com/load-balancing/pools/create-pool/).

---

## Per-endpoint Host header override

When your application needs specialized routing (`CNAME` setup or custom hosts like Heroku), change the `Host` header used in health monitor requests. For more details, refer to [Override HTTP Host headers](https://developers.cloudflare.com/load-balancing/additional-options/override-http-host-headers/).

---

## API commands

The Cloudflare API supports the following commands for pools. Examples are given for user-level endpoint but apply to the account-level endpoint as well.

| Command                                                                                                                                          | Method | Endpoint                                                   |
| ------------------------------------------------------------------------------------------------------------------------------------------------ | ------ | ---------------------------------------------------------- |
| [Create Pool](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/create/)                               | POST   | accounts/:account\_id/load\_balancers/pools                |
| [Delete Pool](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/delete/)                               | DELETE | accounts/:account\_id/load\_balancers/pools/:id            |
| [List Pools](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/list/)                                  | GET    | accounts/:account\_id/load\_balancers/pools                |
| [Pool Details](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/get/)                                 | GET    | accounts/:account\_id/load\_balancers/pools/:id            |
| [Pool Health Details](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/subresources/health/methods/get/)      | GET    | account/:account\_id/load\_balancers/pools/:id/health      |
| [Overwrite specific properties](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/edit/)               | PATCH  | accounts/:account\_id/load\_balancers/pools/:id            |
| [Overwrite existing pool](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/update/)                   | PUT    | accounts/:account\_id/load\_balancers/pools/:id            |
| [Preview Pool](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/subresources/health/methods/create/)          | POST   | account/:account\_id/load\_balancers/pools/:id/preview     |
| [List Pool References](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/subresources/references/methods/get/) | GET    | accounts/:account\_id/load\_balancers/pools/:id/references |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/pools/","name":"Pools"}}]}
```

---

---
title: Use Pages as an origin for Load Balancing
description: This tutorial is intended as an introductory example of how you can leverage Cloudflare's global traffic management.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Use Pages as an origin for Load Balancing

**Last reviewed:**  almost 2 years ago 

This tutorial is intended as an introductory example of how you can leverage Cloudflare's global traffic management.

The following sections will guide you through setting up an [active-passive failover](https://developers.cloudflare.com/load-balancing/load-balancers/common-configurations/#active---passive-failover) load balancer with [Cloudflare Pages](https://developers.cloudflare.com/pages/) as one of the [endpoints](https://developers.cloudflare.com/load-balancing/understand-basics/load-balancing-components/#endpoints), while also going into details about the Load Balancing dashboard workflow, and some important field values and troubleshooting.

## Use cases

This setup can be useful if you are migrating your production website or application to Pages or if you just want to have a backup or a personalized web page for when your primary origin goes down.

## Before you begin

Make sure you:

* Are familiar with the Cloudflare [Load Balancing components](https://developers.cloudflare.com/load-balancing/understand-basics/load-balancing-components/).
* Own a domain and use Cloudflare as a [primary DNS provider](https://developers.cloudflare.com/dns/zone-setups/full-setup/).
* Have [deployed a website or application](https://developers.cloudflare.com/pages/get-started/git-integration/) with Cloudflare Pages.
* Have [enabled Load Balancing](https://developers.cloudflare.com/load-balancing/get-started/enable-load-balancing/) in your account.

## Create health monitor

Although you can create all the components in the **Create Load Balancer** workflow, using the **Manage Monitors** and **Manage Pools** sections separately makes it easier to test and troubleshoot the configurations of each of these components before bringing them together in a load balancer.

Monitors define the criteria based on which an endpoint will be considered healthy or not. Start by setting up a monitor as follows.

1. In the Cloudflare dashboard, go to the **Load Balancing** page.  
[ Go to **Load Balancing** ](https://dash.cloudflare.com/?to=/:account/load-balancing)
2. Select the **Monitors** tab and then **Create monitor**.
3. Give the monitor a descriptive name and confirm the other fields are filled in as the following:

| Field | Value |
| ----- | ----- |
| Type  | HTTP  |
| Path  | /     |
| Port  | 80    |

1. Under **Advanced health check settings**, keep the default values and enable the **Follow Redirects** option.  
When you are using a service like Cloudflare Pages, it is possible that requests from the health monitor - as well as the ones from your visitors - are redirected before reaching their destination. Enabling this option prevents the monitor from reporting an unhealthy endpoint when it actually has only been redirected (with a `301` code, for example).

Tip

You can name the monitor after the parameters you have defined. For example: `HTTP - 200 - Follow Redirects`.

This way you can easily remember the criteria a certain monitor is using when you decide to attach it to other endpoints as well.

1. Select **Save** to confirm.

## Create pools

Pools hold information about where the health monitor requests and your visitors requests will be directed to.

To support the [use cases](#use-cases) mentioned above, and assuming you only have one origin server for your production website and one for the Cloudflare Pages instance, create two pools with one endpoint each:

Important

The endpoint pointing to [Cloudflare Pages](https://developers.cloudflare.com/pages/) must have **host header** filled in with the project domain (`<project>.pages.dev`) for it to resolve correctly. You can find a reference table for correct setup in Step 8 below.

Failing to add the host header will result in [response code mismatch error](https://developers.cloudflare.com/load-balancing/troubleshooting/common-error-codes/#response-code-mismatch-error) for the monitor, and [Error 1000: DNS points to prohibited IP](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-1xxx-errors/error-1000/) for visitors (if the load balancer is enabled despite the unhealthy monitor status).

1. In the Cloudflare dashboard, go to the **Load Balancing** page.  
[ Go to **Load Balancing** ](https://dash.cloudflare.com/?to=/:account/load-balancing)
2. Select the **Pools** tab and then **Create monitor**.
3. For the first pool, start by filling out the fields:
* A name for the pool (must be unique). Suggestion: `primary`
* A description to provide more details on the name. Suggestion: `production website`
1. Leave the choice for [**Endpoint Steering**](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/) as is. Since each pool will only have one endpoint, this steering method will not interfere in this case.
2. Add your origin server as an endpoint with the following information:
* A name for the endpoint (must be unique). Suggestion: `my-website`.
* The endpoint IP address or hostname.  
Warning  
As exemplified in Step 8 below, when using Cloudflare as an endpoint, **do not** specify one of Cloudflare's anycast IP addresses. Because these IPs can change at any time, you should use a hostname instead.
* The endpoint [weight](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/#weights), which can be set to `1`. Since each pool will only have one endpoint, the endpoint weight will not make a difference in this case.
* A [hostname](https://developers.cloudflare.com/load-balancing/additional-options/override-http-host-headers/) by selecting **Add host header**.  
Warning  
If your production website is hosted on a platform like Cloudflare Pages, where you have a default subdomain (`example.pages.dev`) and then configure a [custom domain](https://developers.cloudflare.com/pages/configuration/custom-domains) (`my-app.com`), you will need to add a host header to avoid failing the health monitor request.
1. Finish configuring the first pool with the following information:
* Leave the **Health Threshold** set to `1`. Since each pool will only have one endpoint, this is the only possible value for this field.
* Select the **Monitor** configured in the previous step.
* Select **Health Check Regions** to choose from which [locations](https://developers.cloudflare.com/load-balancing/monitors/#health-monitor-regions) Cloudflare should send monitor requests to periodically test the endpoint health.
1. Select **Save**
2. Repeat the process for the second pool using the following values:

| Field                      | Value                                   |
| -------------------------- | --------------------------------------- |
| Pool name                  | secondary                               |
| Description                | Pages version                           |
| Endpoint steering          | <default>                               |
| Endpoint name              | my-pages-website                        |
| Endpoint address           | <your custom domain or Pages subdomain> |
| Weight                     | 1                                       |
| Host (**Add host header**) | <your custom domain or Pages subdomain> |
| Health threshold           | 1                                       |
| Monitor                    | <monitor defined on previous step>      |
| Health check regions       | <select region of your choice>          |

## Check the endpoints health status

Before setting up the load balancer:

1. In the Cloudflare dashboard, go to the **Load Balancing** page.  
[ Go to **Load Balancing** ](https://dash.cloudflare.com/?to=/:account/load-balancing)
2. Go to the **Pools** tab.
3. Find the pools you created in the list and check if their status is `Healthy`. You might have to refresh the page.
4. Expand each pool entry to confirm that the health status for endpoints within them is also `Healthy`.

The basic principle is that, if both your production website and your Cloudflare Pages project are live and directly accessible via browser, the monitors should also be able to get a `200` code as HTTP response.

Revise your pools and monitor configurations to confirm they followed the instructions above. If you still find issues, refer to [Troubleshooting](https://developers.cloudflare.com/load-balancing/troubleshooting/common-error-codes/) or [FAQ](https://developers.cloudflare.com/load-balancing/troubleshooting/load-balancing-faq/#why-is-my-endpoint-or-pool-considered-unhealthy).

## Create load balancer

After confirming the endpoints and monitors are set up correctly and return the expected health status, create the load balancer:

1. In the Cloudflare dashboard, go to the **Load Balancing** page.  
[ Go to **Load Balancing** ](https://dash.cloudflare.com/?to=/:account/load-balancing)
2. Select **Create load balancer**.
3. On the **Hostname** page, configure the following and select **Next**.  
   * Enter a **Hostname**, which is the DNS name at which the load balancer is available. Suggestion: for now, you can just add a temporary hostname such as `lb` (so the complete field value would look like `lb.<your_domain>`).  
   * Toggle the orange cloud icon to update the [proxy mode](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/), which affects how traffic is routed and which IP addresses are advertised.  
   * Select your preferred option for [session affinity](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/) and [adaptive routing](https://developers.cloudflare.com/load-balancing/understand-basics/adaptive-routing/).
4. On the **Add a Pool** page, configure the following and select **Next**.  
   * Select the first pool you created previously and select **Add Pool**.  
   * Do the same for the second pool and reorder them if needed. For the purposes of this tutorial, your production website pool would be the first (`primary`) and the Cloudflare Pages pool would be the second (`secondary`).  
   * If needed, update the [**Fallback Pool**](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/#fallback-pools). For the purposes of this tutorial, you can leave this pointing to your secondary pool.
5. On the **Monitors** page, review the monitors attached to your pools and the expected health status, and select **Next**.
6. On the **Traffic Steering** page, make sure **Off** is selected. This means the load balancer will follow the order established on the **Add a Pool** section (Step 3 above), achieving an [Active - Passive Failover](https://developers.cloudflare.com/load-balancing/load-balancers/common-configurations/#active---passive-failover) configuration.
7. For the purposes of this tutorial, leave the [**Custom Rules**](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/) option empty.
8. On the **Review** page, review your configuration and select **Save as Draft**.

A DNS record of the type `LB` will be created under [**DNS** \> **Records** ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns/records) with the hostname you have defined, and a corresponding load balancer will be added to [**Load Balancing** ↗](https://dash.cloudflare.com/?to=/:account/load-balancing)

## Optional - Deploy on a test hostname

If you have used a temporary hostname for your load balancer, follow the steps below to deploy and test it.

1. In the Cloudflare dashboard, go to the **Load Balancing** page.  
[ Go to **Load Balancing** ](https://dash.cloudflare.com/?to=/:account/load-balancing)
2. In the **Load Balancers** list, locate the load balancer you created under a test hostname (such as `lb`) and enable it.
3. On your browser, request the temporary hostname (`lb.example.com`). You should see the website or application hosted at your primary origin server.
4. Go back to the **Manage Load Balancers** list, select to expand the test load balancer, and disable the primary pool.
5. On a new incognito window of your browser, request the temporary hostname once again. You should see the website or application hosted at your secondary origin server this time.  
If you find issues, revise your pools, monitor, and load balancer configurations to confirm they followed the instructions above. Also refer to [Troubleshooting](https://developers.cloudflare.com/load-balancing/troubleshooting/common-error-codes/) or [FAQ](https://developers.cloudflare.com/load-balancing/troubleshooting/load-balancing-faq/) if needed.

Important

After you confirm everything is working correctly, make sure you re-enable the pools within the load balancer.

## Route production traffic to load balancer

Now that you have set up your load balancer and verified everything is working correctly, you can put the load balancer on a live domain or subdomain:

1. Confirm that your production hostname has the correct [priority order](https://developers.cloudflare.com/load-balancing/load-balancers/dns-records/#priority-order) of DNS records and is covered by an [SSL/TLS certificate](https://developers.cloudflare.com/load-balancing/load-balancers/dns-records/#ssltls-coverage).  
If you have an Enterprise account, also evaluate your application for any excluded paths. For example, you might not want the load balancer to distribute requests directed at your `/admin` path. For any exceptions, set up an [Origin rule](https://developers.cloudflare.com/rules/origin-rules/features/#dns-record).
2. Configure your load balancer to receive production traffic by editing the **Hostname** of your existing load balancer.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/pools/","name":"Pools"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/pools/cloudflare-pages-origin/","name":"Use Pages as an origin for Load Balancing"}}]}
```

---

---
title: Manage pools
description: Learn how to set up and maintain pools.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Manage pools

Within Cloudflare, pools represent your endpoints and how they are organized. As such, a pool can be a group of several endpoints, or you could also have only one endpoint (an origin server, for example) per pool.

If you are familiar with DNS terminology, think of a pool as a “record set,” except Cloudflare only returns addresses that are considered healthy. You can attach health monitors to individual pools for customized monitoring. A pool can have either a single monitor or a monitor group attached — but not both.

For more background information on pools, refer to [Pools](https://developers.cloudflare.com/load-balancing/pools/).

Warning

Since load balancing targets are not limited to origin web servers, the term `endpoints` has been introduced. Refer to [Service-Specific Terms ↗](https://www.cloudflare.com/service-specific-terms-other-terms/) for its use in the context of Cloudflare offerings, and to [load balancing concepts](https://developers.cloudflare.com/load-balancing/understand-basics/load-balancing-components/) or [Reference Architecture](https://developers.cloudflare.com/reference-architecture/architectures/load-balancing/) for use case examples.

On the [Load Balancing API](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/get/), `origin` has been maintained.

---

## Create a pool

* [ Dashboard ](#tab-panel-9180)
* [ API ](#tab-panel-9181)

You can create a pool within the [load balancer workflow](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/) or in the **Pools** tab:

1. Go to **Load Balancing**.
2. Select the **Pools** tab and then **Create pool**.
3. For your pool, enter the following information:  
   * A name (must be unique)  
   * A description to provide more detail on the name  
   * A choice for [**Endpoint Steering**](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/), which affects how your pool routes traffic to each endpoint
4. For each endpoint, enter the following information:  
   * A name (must be unique)  
   * The endpoint address or associated hostname  
   * (Optional) A [**Virtual Network**](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/private-net/cloudflared/tunnel-virtual-networks/). Required when the endpoint has a private IP address.  
   * A [**Weight**](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/#weights)  
   * (Optional) A [hostname](https://developers.cloudflare.com/load-balancing/additional-options/override-http-host-headers/) by clicking **Add host header**  
   * (Optional) The destination port to which the traffic will be served.

Note

If your endpoint is a website or application hosted on [Cloudflare Pages](https://developers.cloudflare.com/pages/), you will need to fill in the host header field with the project domain for it to resolve correctly.

1. Repeat this process for additional endpoints in the pool.
2. (Optional) Set up coordinates for [Proximity Steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/proximity-steering/) on the pool.
3. On the pool, update the following information:  
   * **Health Threshold**:  
   The Health Threshold is the number of healthy endpoints for the pool as a whole to be considered _Healthy_ and receive traffic based on pool order in a load balancer. Increasing this number makes the pool more reliable, but also more likely to become unhealthy.  
   * **Monitor**: Attach a [monitor](https://developers.cloudflare.com/load-balancing/monitors/create-monitor/)  
   * **Health Monitor Regions**: Choose whether to check pool health from [multiple locations](https://developers.cloudflare.com/load-balancing/monitors/#health-monitor-regions), which increases accuracy but can lead to probe traffic to your endpoint  
   * **Pool Notifications**: You can set up new alerts - and view existing alerts - to be notified when pools are enabled or disabled, or pools or endpoints have changes in their [health status](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/).
4. When finished, select **Save**.

For a full list of properties, refer to [Create Pool](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/create/). If you need help with API authentication, refer to [Cloudflare API documentation](https://developers.cloudflare.com/fundamentals/api/).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Load Balancing: Monitors and Pools Write`

Create Pool

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/load_balancers/pools" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "description": "Primary data center - Provider XYZ",

    "name": "primary-dc-1",

    "enabled": false,

    "load_shedding": {

        "default_percent": 0,

        "default_policy": "random",

        "session_percent": 0,

        "session_policy": "hash"

    },

    "minimum_origins": 2,

    "monitor": "f1aba936b94213e5b8dca0c0dbf1f9cc",

    "check_regions": [

        "WEU",

        "ENAM"

    ],

    "origins": [

        {

            "name": "app-server-1",

            "address": "0.0.0.0",

            "enabled": true,

            "weight": 0.56,

            "header": {

                "Host": [

                    "example.com"

                ]

            }

        }

    ],

    "origin_steering": {

        "policy": "random"

    },

    "notification_filter": {

        "origin": {

            "disable": false,

            "healthy": null

        },

        "pool": {

            "disable": false,

            "healthy": null

        }

    }

  }'


```

The response contains the complete definition of the new pool.

Response

```

{

  "success": true,

  "errors": [],

  "messages": [],

  "result": {

    "id": "17b5962d775c646f3f9725cbc7a53df4",

    "created_on": "2021-01-01T05:20:00.12345Z",

    "modified_on": "2021-01-01T05:20:00.12345Z",

    "description": "Primary data center - Provider XYZ",

    "name": "primary-dc-1",

    "enabled": false,

    "load_shedding": {

      "default_percent": 0,

      "default_policy": "random",

      "session_percent": 0,

      "session_policy": "hash"

    },

    "minimum_origins": 2,

    "monitor": "f1aba936b94213e5b8dca0c0dbf1f9cc",

    "check_regions": [

      "WEU",

      "ENAM"

    ],

    "origins": [

      {

        "name": "app-server-1",

        "address": "0.0.0.0",

        "enabled": true,

        "weight": 0.56,

        "header": {

          "Host": [

            "example.com"

          ]

        }

      }

    ],

    "origin_steering": {

      "policy": "random"

    },

    "notification_filter": {

      "origin": {

        "disable": false,

        "healthy": null

      },

      "pool": {

        "disable": false,

        "healthy": null

      }

    }

  }

}


```

After creating the pool, you would also want to [create a new notification](https://developers.cloudflare.com/api/resources/alerting/subresources/policies/methods/create/) with the following parameters specified:

```

"alert_type": "load_balancing_health_alert",

"filters": {

  "pool_id": <<ARRAY_OF_INCLUDED_POOL_IDS>>,

  "new_health": <<ARRAY_OF_STATUS_TRIGGERS>> ["Unhealthy", "Healthy"],

  "event_source": <<ARRAY_OF_OBJECTS_WATCHED>> ["pool", "origin"]

}


```

---

## Edit a pool

* [ Dashboard ](#tab-panel-9176)
* [ API ](#tab-panel-9177)

To edit a pool in the dashboard:

1. Go to **Load Balancing**.
2. Select the **Pools** tab.
3. On a specific pool, select **Edit**.
4. Update settings as needed.
5. Select **Save**.

When you edit a pool with the API, your request type depends on how much you want to edit.

To update specific settings without having to resubmit the entire configuration, use a [PATCH](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/edit/) request. For broader changes, use a [PUT](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/update/) request.

---

## Delete a pool

You cannot delete pools that are in use by load balancers. This includes [geo steering regions](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/geo-steering/#region-steering) pools as well as [fallback pools](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/#fallback-pools).

If you get an error when trying to delete a pool, consider the hostnames listed in the error and [edit the respective load balancers](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/), making sure to remove all references to the pool.

Note

If the pool is referenced by geo steering, the configuration is **not** automatically removed when you change to a different **Traffic Steering** method. To make sure you remove it, select **Geo Steering**, remove the pool, and then apply and save any other necessary changes.

* [ Dashboard ](#tab-panel-9178)
* [ API ](#tab-panel-9179)

To delete a pool in the dashboard:

1. Go to **Load Balancing**.
2. Select the **Pools** tab.
3. On a specific pool, select **Delete**.

To delete a pool using the API, send a [DELETE](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/delete/) request.

---

## Set up alerts

You can configure alerts to receive notifications for changes in the status of your pools.

Pool Enablement

**Who is it for?**

Customers who want to be warned about status changes (enabled/disabled) in their pools.

**Other options / filters**

Available filters include:

* You can search for and add pools from your list of pools. If no pools are selected, the alert will apply to all pools in the account.
* You can also choose the trigger that fires the notification when the Load Balancing pool is **enabled**, **disabled**, and **either enabled or disabled**.
**Included with**

Purchase of [Load Balancing](https://developers.cloudflare.com/load-balancing/get-started/enable-load-balancing/).

**What should you do if you receive one?**

No action is needed.

Load Balancing Health Alert

**Who is it for?**

Customers who want to be warned about [changes in health status](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/) in their pools or origins.

**Other options / filters**

Available filters include:

* You can search for and add pools from your list of pools, as well as **Include future pools** (if all pools are selected).
* You can choose the trigger that fires the notification when the health status becomes **unhealthy**, **healthy**, or **either unhealthy or healthy**
* You can choose the trigger that fires the notification when the event source health status changes in **pool**, **origin**, or **either pool or origin**.
**Included with**

Purchase of [Load Balancing](https://developers.cloudflare.com/load-balancing/get-started/enable-load-balancing/).

**What should you do if you receive one?**

Evaluate [load balancing analytics](https://developers.cloudflare.com/load-balancing/reference/load-balancing-analytics/) to review changes in health status over time.

Refer to [Cloudflare Notifications](https://developers.cloudflare.com/notifications/get-started/) for more information on how to set up an alert.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/pools/","name":"Pools"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/pools/create-pool/","name":"Manage pools"}}]}
```

---

---
title: Monitors
description: Health monitors that check origin server availability.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Monitors

A monitor issues health monitor requests at regular intervals to evaluate the health of each endpoint within a [pool](https://developers.cloudflare.com/load-balancing/pools/).

When a pool [becomes unhealthy](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/), your load balancer takes that pool out of the endpoint rotation.

    flowchart RL
      accTitle: Load balancing monitor flow
      accDescr: Monitors issue health monitor requests, which validate the current status of servers within each pool.
      Monitor -- Health Monitor ----> Endpoint2
      Endpoint2 -- Response ----> Monitor
      subgraph Pool
      Endpoint1((Endpoint 1))
      Endpoint2((Endpoint 2))
      end

Health monitor requests that result in a status change for an endpoint are recorded as events in the Load Balancing event logs.

Note

Health monitors associated with load balancers are different from standalone [Health Checks](https://developers.cloudflare.com/health-checks/). For an overview of how the Cloudflare Load Balancing solution works, refer to [Load Balancing components](https://developers.cloudflare.com/load-balancing/understand-basics/load-balancing-components/).

---

## Properties

For an up-to-date list of monitor properties, refer to [Monitor properties](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/methods/list/) in our API documentation.

---

## Create monitors

For step-by-step guidance, refer to [Create monitors](https://developers.cloudflare.com/load-balancing/monitors/create-monitor/).

### Monitor Groups

Monitor Groups let you combine multiple health monitors into a single logical group to create more accurate, intelligent health checks for your applications. By aggregating results from several monitors, you can better reflect real application health and improve traffic steering resilience. For more details, refer to the [Monitor Groups](https://developers.cloudflare.com/load-balancing/monitors/monitor-groups/) documentation page.

---

## Health monitor regions

When you [attach a monitor to a pool](https://developers.cloudflare.com/load-balancing/monitors/create-monitor/#create-a-monitor), you can select multiple regions to increase reporting accuracy.

For each option selected in a pool's **Health Monitor Regions**, Cloudflare sends health monitor requests from three separate data centers in that region.

![Health monitor requests come from three data centers within each selected region.](https://developers.cloudflare.com/_astro/health-check-component.wo0_f7k-_Z1C61Ll.webp) 

If the majority of data centers for that region pass the health monitor requests, that region is considered healthy. If the majority of regions is healthy, then the endpoint itself will be considered healthy.

### Configurations

**All Data Centers (Enterprise only)**

Health monitor probes are sent from every single data center in Cloudflare’s network to the endpoints within the associated pool. This allows probes to hit each endpoint during intervals set by the customer.

**All Regions (Enterprise only)**

Three health monitor probes per region are sent to each endpoint in the associated pool. There are a total of 13 regions, resulting in 39 probes.

**Regional**

Three health monitor probes are sent from each specified region within the pool configuration.

Warning

Because of how Cloudflare checks health from [multiple regions](#health-monitor-regions), adding multiple regions — or choosing to check health from **All Data Centers** — can send a lot of traffic to your endpoint.

The same problem can occur when setting low values for a monitor's **Interval**.

---

## Host header prioritization

The host headers used on health monitor requests can be configured either [on the monitor itself](https://developers.cloudflare.com/load-balancing/monitors/create-monitor/) or on the [endpoints within a pool](https://developers.cloudflare.com/load-balancing/pools/create-pool/).

When a host header is specified both on the monitor and on the endpoint, the host header configured on the endpoint takes precedence over the host header configured on the monitor.

When no host header is specified, Cloudflare uses the **Endpoint Address** configured on the endpoints as the host header for the health monitor requests.

For more details, refer to [Override HTTP Host headers](https://developers.cloudflare.com/load-balancing/additional-options/override-http-host-headers/).

---

## API commands

The Cloudflare API supports the following commands for monitors. Examples are given for user-level endpoint but apply to the account-level endpoint as well.

| Command                                                                                                                                         | Method | Endpoint                                                   |
| ----------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---------------------------------------------------------- |
| [Create Monitor](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/methods/create/)                        | POST   | accounts/:account\_id/load\_balancers/monitors             |
| [Delete Monitor](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/methods/delete/)                        | DELETE | accounts/:account\_id/load\_balancers/monitors/:id         |
| [List Monitors](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/methods/list/)                           | GET    | accounts/:account\_id/load\_balancers/monitors             |
| [Monitor Details](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/methods/get/)                          | GET    | accounts/:account\_id/load\_balancers/monitors/:id         |
| [Overwrite specific properties](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/methods/edit/)           | PATCH  | accounts/:account\_id/load\_balancers/monitors/:id         |
| [Overwrite existing monitor](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/methods/update/)            | PUT    | accounts/:account\_id/load\_balancers/monitors/:id         |
| [Preview Monitor](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/subresources/previews/methods/create/) | POST   | accounts/:account\_id/load\_balancers/monitors/:id/preview |

## Supported protocols

The following table summarizes the different types of monitors available in Cloudflare Load Balancing, their monitoring types, and how each health check process evaluates the success criteria to determine endpoint health:

| Monitor type | Monitoring type    | Description                                                                                                                                                                                | Health check process                                                                                                                                                                                                                                                                                                                                                                                                                                                           | Success criteria                                                                                                                                   |
| ------------ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| HTTP/HTTPS   | Public and private | Used for HTTP and HTTPS endpoints with specific protocol attributes.                                                                                                                       | The probe is configured with settings and success criteria such as Method, Simulate Zone, Follow Redirects, Request Headers, and Response Body. The probe then evaluates the configured success criteria using the HTTP protocol. Throughout the configured timeout period, the TCP connection is kept active using [keep-alives](https://developers.cloudflare.com/fundamentals/reference/tcp-connections/#tcp-connections-and-keep-alives), even if no response is received. | Success is based on meeting the configured HTTP success criteria. No response within the configured timeout and retries is considered unhealthy.   |
| TCP          | Public and private | Checks TCP connectivity by attempting to open a connection to the endpoint.                                                                                                                | The monitor sends a TCP SYN message to the specified port. A successful health check requires receiving a SYN/ACK message to establish the connection. The connection is closed by sending a FIN or RST packet, or by receiving a FIN packet from the endpoint.                                                                                                                                                                                                                | Failure to establish a TCP connection within the configured timeout and retries is considered unhealthy.                                           |
| ICMP Ping    | Public and Tunnel  | Confirms basic Layer 3 (L3) connectivity to the endpoint using ICMP. The endpoints need to be allowed to reply to ICMP packets and any intervening networking equipment must support ICMP. | The monitor sends an ICMP/ICMPv6 echo request (ping) and expects an ICMP/ICMPv6 echo reply from the endpoint.                                                                                                                                                                                                                                                                                                                                                                  | The endpoint must reply to the ICMP ping within the configured timeout and retries to be considered healthy.                                       |
| UDP-ICMP     | Public and Tunnel  | UDP-ICMP monitor works by sending a UDP probe packet after ICMP Ping monitor completes as healthy.                                                                                         | After receiving a successful ICMP reply, the monitor sends a UDP probe packet to the endpoint. If no ICMP Port Unreachable message is received, the endpoint is considered healthy.                                                                                                                                                                                                                                                                                            | If the monitor receives an ICMP Port Unreachable message within the configured timeout and retries, the endpoint is considered unhealthy.          |
| SMTP         | Public             | Verifies SMTP availability at the application layer.                                                                                                                                       | The monitor establishes a TCP connection and sends an SMTP HELO command. It expects a reply with code 250\. The monitor then sends an SMTP QUIT command, expecting a reply with code 221\. At the end of each interval, the TCP connection is closed by sending a TCP FIN packet.                                                                                                                                                                                              | The endpoint must respond with correct SMTP codes (250 for HELO, 221 for QUIT) within the configured timeout and retries to be considered healthy. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/monitors/","name":"Monitors"}}]}
```

---

---
title: Manage monitors
description: Learn how to set up and maintain monitors for your load balancer.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Manage monitors

A monitor issues health monitor requests at regular intervals to evaluate the health of each endpoint within a [pool](https://developers.cloudflare.com/load-balancing/pools/).

When a pool [becomes unhealthy](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/), your load balancer takes that pool out of the endpoint rotation.

For more details about monitors, refer to [Monitors](https://developers.cloudflare.com/load-balancing/monitors/).

---

## Create a monitor

* [ Dashboard ](#tab-panel-9174)
* [ API ](#tab-panel-9175)

**Set up the monitor**

You can create a monitor within the [load balancer workflow](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/) or in the **Monitors** tab:

1. Go to **Load Balancing**.
2. Select the **Monitors** tab.
3. Select **Create monitor**.
4. Add the following information:  
   * **Type**: The protocol to use for health monitors  
         * _Non-enterprise customers_: Choose **HTTP**, **HTTPS**, or **TCP**.  
         * _Enterprise customers_: Choose **HTTP**, **HTTPS**, **TCP**, **UDP ICMP**, **ICMP Ping**, or **SMTP**.  
   * **Path**: The endpoint path to run health monitor requests against  
   * **Port**: The destination port for health monitors
5. For additional settings, select **Advanced health monitor settings**:  
   * **Interval**:  
         * By increasing the default, you can improve failover time, but you may also increase load on your endpoints.  
         * Minimum time in seconds is 60 (Pro), 15 (Business), and 10 (Enterprise).  
   * **Timeout** and **Retries**:  
         * The health monitor request will return unhealthy if it exceeds the duration specified in **Timeout** (and exceeds this duration more times than the specified number of **Retries**).  
   * **Expected Code(s)**: The expected HTTP response codes listed individually (`200`, `302`) or as a range (for example, entering `2xx` would cover all response codes in the `200` range).  
   * **Response Body**:  
         * Looks for a case-insensitive substring in the response body.  
         * Make sure that the value is relatively static and within the first 10 KB of the HTML page.  
   * **Simulate Zone**:  
         * It is recommended to use the same zone in which the Load Balancer exists.  
         * Changes the egress zone settings of a health monitor request to ensure compatibility with features like [Authenticated Origin Pulls (mTLS)](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/), [Argo Smart Routing](https://developers.cloudflare.com/argo-smart-routing/), [Bring your own CA (mTLS)](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/), [Dedicated CDN Egress IPs](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/), and [HTTP/2 to Origin](https://developers.cloudflare.com/speed/optimization/protocol/http2-to-origin/).  
   * **Follow Redirects**:  
         * Instead of reporting a `301` or `302` code as unhealthy, the health monitor request follows redirects to the final endpoint.  
   * **Configure Request Header(s)**:  
         * Useful if your endpoints are expecting specific incoming headers.  
   * **Header**:  
         * The HTTP request headers to send in the health monitor. It is recommended that you set a Host header by default. The User-Agent header cannot be overridden. This parameter is only valid for HTTP and HTTPS monitors.
6. Select **Save**.

Note

To increase confidence in pool status, you can also increase the `consecutive_up` and `consecutive_down` fields when [creating a monitor with the API](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/methods/create/).

To become healthy or unhealthy, monitored endpoints must pass this health monitor request the consecutive number of times specified in these parameters.

**Prepare your servers**

Make sure that your firewall or web server does not block or rate limit your configured health monitors or requests associated with [Cloudflare IP addresses ↗](https://www.cloudflare.com/ips).

Each health monitor has the HTTP user-agent of `"Mozilla/5.0 (compatible; Cloudflare-Traffic-Manager/1.0; +https://www.cloudflare.com/traffic-manager/; pool-id: $poolid)"`, where the `$poolid` is the first 16 characters of the [associated pool](https://developers.cloudflare.com/load-balancing/pools/).

Warning

If you know that your endpoint is healthy but Load Balancing is reporting it as unhealthy, refer to our [Monitor troubleshooting guide](https://developers.cloudflare.com/load-balancing/troubleshooting/load-balancing-faq/#why-is-my-endpoint-or-pool-considered-unhealthy).

**Attach the monitor to a pool**

Once your monitor is created, you need to attach it to a pool:

1. Go to **Load Balancing**.
2. Select the **Pools** tab.
3. On a specific pool, select **Edit**.
4. Update the following information:  
   * **Monitor**: Select your monitor.  
   * **Health Monitor Regions:** Specifies geographic regions from which Cloudflare should send health monitor requests. Because of [how monitors check pool health](https://developers.cloudflare.com/load-balancing/monitors/#health-monitor-regions), selecting multiple regions could increase the load on your servers.  
   * **Notification E-mail:** Contains email addresses that receive notifications (individual, mailing list address, PagerDuty address).
5. Select **Save**. The status of your health monitor will be _unknown_ until the results of the first check are available.

**Set up the monitor**

For a full list of monitor properties, refer to [Create Monitor](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/methods/create/). If you need help with API authentication, refer to [Cloudflare API documentation](https://developers.cloudflare.com/fundamentals/api/).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Load Balancing: Monitors and Pools Write`

Create Monitor

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/load_balancers/monitors" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "type": "https",

    "description": "Login page monitor",

    "method": "GET",

    "path": "/health",

    "header": {

        "Host": [

            "example.com"

        ],

        "X-App-ID": [

            "abc123"

        ]

    },

    "port": 8080,

    "timeout": 3,

    "retries": 0,

    "interval": 90,

    "expected_body": "alive",

    "expected_codes": "2xx",

    "follow_redirects": true,

    "allow_insecure": true,

    "consecutive_up": 3,

    "consecutive_down": 2,

    "probe_zone": "example.com"

  }'


```

The response contains the complete definition of the new monitor.

Response

```

{

  "success": true,

  "errors": [],

  "messages": [],

  "result": {

    "id": ":monitor-id",

    "created_on": "2021-01-01T05:20:00.12345Z",

    "modified_on": "2021-01-01T05:20:00.12345Z",

    "type": "https",

    "description": "Login page monitor",

    "method": "GET",

    "path": "/health",

    "header": {

      "Host": [

        "example.com"

      ],

      "X-App-ID": [

        "abc123"

      ]

    },

    "port": 8080,

    "timeout": 3,

    "retries": 0,

    "interval": 90,

    "expected_body": "alive",

    "expected_codes": "2xx",

    "follow_redirects": true,

    "allow_insecure": true,

    "consecutive_up": 3,

    "consecutive_down": 2,

    "probe_zone": "example.com"

  }

}


```

**Prepare your servers**

Make sure that your firewall or web server does not block or rate limit your configured health monitors or requests associated with [Cloudflare IP addresses ↗](https://www.cloudflare.com/ips).

Each health monitor has the HTTP user-agent of `"Mozilla/5.0 (compatible; Cloudflare-Traffic-Manager/1.0; +https://www.cloudflare.com/traffic-manager/; pool-id: $poolid)"`, where the `$poolid` is the first 16 characters of the [associated pool](https://developers.cloudflare.com/load-balancing/pools/).

Warning

If you know that your endpoint is healthy but Load Balancing is reporting it as unhealthy, refer to our [Monitor troubleshooting guide](https://developers.cloudflare.com/load-balancing/troubleshooting/load-balancing-faq/#why-is-my-endpoint-or-pool-considered-unhealthy).

**Attach the monitor to a pool**

Once your monitor is created, save its `id` property. Include this value in the `monitor` parameter when [creating your pool](https://developers.cloudflare.com/load-balancing/pools/create-pool/#create-a-pool).

---

## Edit a monitor

* [ Dashboard ](#tab-panel-9170)
* [ API ](#tab-panel-9171)

To edit a monitor in the dashboard:

1. Go to **Load Balancing**.
2. Select **Monitors**.
3. On a specific monitor, select **Edit**.
4. Update settings as needed.
5. Select **Save**.

When you edit a monitor with the API, your request type depends on how much you want to edit.

To update specific settings without having to resubmit the entire configuration, use a [PATCH](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/methods/edit/) request. For broader changes, use a [PUT](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/methods/update/) request.

---

## Delete a monitor

* [ Dashboard ](#tab-panel-9172)
* [ API ](#tab-panel-9173)

To delete a monitor in the dashboard:

1. Go to **Load Balancing**.
2. Select the **Monitors** tab.
3. On a specific monitor, select **Delete**.

To delete a monitor using the API, send a [DELETE](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/methods/delete/) request.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/monitors/","name":"Monitors"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/monitors/create-monitor/","name":"Manage monitors"}}]}
```

---

---
title: Monitor Groups
description: Group monitors for coordinated health checking.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Monitor Groups

Group multiple health monitors together to create sophisticated health checks for your applications, ensuring more intelligent and resilient traffic steering.

You can group multiple health monitors to build sophisticated health checks that more accurately reflect your application's true health. A Monitor Group allows you to combine several independent monitors, define aggregation logic, and use the collective result to determine the health of an origin pool.

Grouping multiple health monitors enables more intelligent and resilient failover. For example, you can require that both a general API gateway monitor and a specific login service monitor must be healthy for a pool to receive traffic.

## Availability

Monitor Groups are only available to customers on an Enterprise plan with the Load Balancing subscription.

Configuration is available via the [API](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitor%5Fgroups/methods/create/) only.

Note

Pools assigned to a monitor group via the API will appear as **Not monitored** on the dashboard.

## How it works

When you attach a Monitor Group to a pool, the health of that pool is determined by aggregating the results of all enabled monitors within the group.

The sections below explain how monitor groups influence health status, latency, and result handling.

## Endpoint health with Monitor Groups

A Monitor Group determines an endpoint's health using a combination of critical monitor overrides and quorum-based consensus.

**Critical Monitor Override** (`must_be_healthy`): You can designate a monitor as critical by setting `"must_be_healthy": true`. If a monitor with this setting fails its health check against an endpoint, that specific endpoint is immediately marked as unhealthy. This happens regardless of the status reported by other monitors in the group for that same endpoint. This provides a definitive override for essential services.

**Quorum-Based Health**: In the absence of a failure from a `must_be_healthy` monitor, an endpoint's health is determined by a quorum of all other active monitors.

* An endpoint is considered unhealthy only if more than 50% of its assigned monitors report it as unhealthy.
* Monitors marked as `"monitoring_only": true` are excluded from the quorum calculation. They will still run and can trigger notifications, but they do not vote on the endpoint's health status.
* Monitors marked as `disabled` will not send monitoring requests to any associated pool. They are also excluded from the quorum calculation.

This quorum system prevents an endpoint from being prematurely marked as unhealthy due to a transient failure from a single, non-critical monitor.

## Latency for Steering

For pools using Dynamic Steering, the pool's latency is calculated as the average latency of all its enabled, non-monitoring-only monitors. This aggregated RTT (Round Trip Time) value provides a more holistic view of an origin's performance and is used to make steering decisions.

## Result handling for different intervals

If monitors in a group have different check intervals, the group uses the last available result from each monitor until it is refreshed. For example, if one monitor runs every 10 seconds and another every 30 seconds, the 30-second monitor's result is considered valid for the full 30 seconds until its next run completes.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/monitors/","name":"Monitors"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/monitors/monitor-groups/","name":"Monitor Groups"}}]}
```

---

---
title: Private Network Load Balancing
description: Use Private Network Load Balancing to load balance traffic between servers within a data center or between private applications, and eliminate the need for hardware appliances.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Private Network Load Balancing

Private Network Load Balancing enables you to load balance traffic between servers within a data center ([endpoint steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/)) and between private applications. This helps you eliminate the need for hardware appliances and facilitates the migration of your infrastructure to the cloud, providing advantages such as elastic scalability and enhanced reliability.

Private Network Load Balancing supports not only public IPs but also virtual IPs and private IPs as endpoint values.

Note

This page assumes a certain level of familiarity with how the Cloudflare Load Balancing solution works. For an introductory overview refer to [Load Balancing components](https://developers.cloudflare.com/load-balancing/understand-basics/load-balancing-components/).

---

## Off-ramps

Off-ramps create a direct and secure way for Cloudflare to connect into your networks that are not publicly available.

Since traffic steering decisions or failover mechanisms rely on the health information of pools and endpoints, being able to input your virtual or private IPs directly as endpoints within your load balancer means you can better leverage existing health monitoring.

### Tunnel

Currently, to be able to connect to private IP origins, Cloudflare load balancers require a [Cloudflare tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/) with an associated [virtual network (VNet)](https://developers.cloudflare.com/cloudflare-one/networks/virtual-networks/). If you are connecting to your endpoints using a [published application route](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/routing-to-tunnel/public-load-balancers) a VNet is not necessary.

Once the endpoint and virtual network (VNet) tunnel association is configured, Cloudflare can determine not only the tunnel health but also the health of the corresponding virtual or private IP targets.

Refer to [Set up Private Network Load Balancing for Public traffic to Tunnel](https://developers.cloudflare.com/load-balancing/private-network/public-to-tunnel/) for a detailed guide.

### Cloudflare WAN

Private Network Load Balancing supports off-ramping traffic for Cloudflare WAN (formerly Magic WAN) tunnels, such as GRE, IPSec or CNI tunnels. For more information refer to the [Set up Private Network Load Balancing with Cloudflare WAN](https://developers.cloudflare.com/load-balancing/private-network/cloudflare-wan/).

---

## On-ramps

Private Network Load Balancing on-ramps, on the other hand, refer to secure paths between the end-user request and the Cloudflare network. Cloudflare Load Balancing supports traffic from [CDN](https://developers.cloudflare.com/cache/), [Spectrum](https://developers.cloudflare.com/spectrum/), [Cloudflare One Client](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/cloudflare-one-client/) and [Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/) and forward that traffic to a load balancer, and then egress to an endpoint behind any off-ramp (CDN/CNI/IPSec/GRE/Tunnel). Your traffic can ingress and egress by any on-ramp/off-ramp combination.

Note

When using [Spectrum](https://developers.cloudflare.com/spectrum/) as an on-ramp and [Cloudflare WAN](https://developers.cloudflare.com/load-balancing/private-network/#cloudflare-wan) as an off-ramp the [proxy protocol](https://developers.cloudflare.com/spectrum/how-to/enable-proxy-protocol/) setting in Spectrum is not supported.

---

## Use cases

* **Requests originating from the public Internet and directed to a private/internal service**: You can route requests from the Internet to your internal services on internal IPs - such as accounting or production automation systems - using [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/).
* **Intelligent traffic routing**: Benefit from failover for your private traffic and have the ability to monitor the health of these IP targets directly, rather than load balancing to a tunnel and only monitoring the health of the tunnel itself.
* **Host applications on non-standard ports**: Easily specify and route traffic to applications hosted on private IP addresses using non-standard ports, allowing greater flexibility in service configuration without requiring changes to existing infrastructure.
* **Public and Private Load Balancers**: Public LBs can direct Internet traffic to private IP addresses, supporting all L7 products like WAF and API Shield. Private LBs direct traffic originating from private networks to private IP addresses and require an on-ramp like the Cloudflare One Client or Cloudflare WAN.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/private-network/","name":"Private Network Load Balancing"}}]}
```

---

---
title: Set up Private Network Load Balancing with Cloudflare WAN
description: Set up private load balancing with Cloudflare WAN.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Set up Private Network Load Balancing with Cloudflare WAN

Consider the following steps to learn how to configure Private Network Load Balancing solution, using [Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/) (formerly Magic WAN) as the on-ramp and off-ramp to securely connect to your private or internal services.

One of the pre-requisites to using Private Network Load Balancing (PNLB) with Cloudflare WAN is having Cloudflare WAN set up in your account and having completed onboarding. You can connect with a Cloudflare One Appliance, or your own hardware via an IPsec or GRE tunnel. Check out the [Cloudflare WAN documentation](https://developers.cloudflare.com/cloudflare-wan/get-started/) for more details or to get started.

## 1\. Create Load Balancer Pools

Load Balancer Pools are logical groupings of endpoints — typically organized by physical datacenter or geographic region. The endpoints in the pool are the destinations where traffic is ultimately routed.

Note

Endpoints accessed via Cloudflare WAN must be accessible in and assigned to the default VNET.

Warning

The IP destination addresses must also be routable in your Cloudflare WAN configuration. Please contact your Cloudflare account team to confirm that the addresses are available in your configuration.

Pools can be created using either the Cloudflare dashboard or the API. Refer to the [Create a pool](https://developers.cloudflare.com/load-balancing/pools/create-pool/#create-a-pool) documentation section for more information.

## 2\. Create an Account Load Balancer with a Private IP

1. Go to **Load Balancing** at the account level and select **Create a Load Balancer**.
2. Select **Private Load Balancer**.
3. On the next step you can choose to associate this load balancer with either:
* A CGNAT IP from the Cloudflare range or
* A custom [RFC1918 address ↗](https://datatracker.ietf.org/doc/html/rfc1918).
1. Add a descriptive name to identify your Load Balancer.
2. Proceed through the setup.

After selecting an IP address and completing the setup, you will be redirected to the Load Balancing dashboard. You can locate your load balancer using the search bar or by filtering for **Private** load balancers. Be sure to note the assigned IP address, as it will be required in the following steps.

Note

Traffic from your load balancer will appear to originate from one of Cloudflare's IP addresses. These IP addresses must be whitelisted to ensure proper traffic flow. Ensure your routing is properly configured to return traffic to your IPsec/GRE tunnels and not the public Internet. Private Load Balancers created with a Cloudflare private IP address will receive a default address in the CGNAT range `100.112.0.0`. This IP address is configurable. Refer to [Cloudflare source IP range](https://developers.cloudflare.com/cloudflare-wan/configuration/how-to/configure-cloudflare-source-ips/) to learn more.

## 3\. FQDN override (optional)

If you want your load balancer and its endpoints to be transparently accessible to users via a hostname, you can create a DNS record in your internal DNS system or create an override in Cloudflare that maps the hostname to the Load Balancer's IP address. This ensures that traffic destined for the hostname resolves to the correct IP.

To create the override, follow these steps:

1. In **Gateway**, select **Firewall policies**.
2. In the **DNS** tab, create an override where:  
   * The **Selector** equals `Host`  
   * The **Operator** equals `is`  
   * The **Value** is the hostname you wish to associate with your load balancer.
3. Set the **Action** to _Override_, and in **Override Hostname**, enter the IP address of your Private Load Balancer.

Requests to the hostname will now resolve to your private load balancer.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/private-network/","name":"Private Network Load Balancing"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/private-network/cloudflare-wan/","name":"Set up Private Network Load Balancing with Cloudflare WAN"}}]}
```

---

---
title: Set up Private Network Load Balancing for Public traffic to Tunnel
description: Load balance public traffic to private origins via Tunnel.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Set up Private Network Load Balancing for Public traffic to Tunnel

Consider the following steps to learn how to configure Private Network Load Balancing solution, using [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/) as the off-ramp to securely connect to your private or internal services.

## 1\. Configure a Cloudflare tunnel with an assigned virtual network

The specific configuration steps can vary depending on your infrastructure and services you are looking to connect. If you are not familiar with Cloudflare Tunnel, the pages linked on each step provide more guidance.

1. [Create a tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/get-started/create-remote-tunnel/#1-create-a-tunnel) to connect your data center to Cloudflare.
2. Create a [virtual network](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/private-net/cloudflared/tunnel-virtual-networks/) and assign it to the tunnel you configured in the previous step.

* [ Dashboard ](#tab-panel-9182)
* [ cli ](#tab-panel-9183)

To create a virtual network:

1. In the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), go to **Zero Trust** \> **Settings** \> **WARP Client** and find the **Virtual networks** setting.
2. Select **Add new** or **Manage** \> **Create virtual network** to create virtual networks.
3. Define your virtual network name and select **Save**.

To assign the virtual network to the tunnel:

1. Go to **Networks** \> **Tunnels**.
2. Select the tunnel you created in the previous steps and select **Configure**.
3. Under **Private Network**, select **Add a private network**.
4. Specify an IP range under **CIDR** and select the virtual network under **Additional settings**.
5. Select **Save private network**.

To create a virtual network:

Terminal window

```

cloudflared tunnel vnet add <VNET_NAME>


```

To assign the virtual network to the tunnel:

Terminal window

```

cloudflared tunnel route ip add --vnet <VNET_NAME> <IP_RANGE> <TUNNEL_NAME>


```

## 2\. Configure Cloudflare Load Balancing

Once you have Cloudflare tunnels with associated virtual networks (VNets) configured, the VNets can be specified for each endpoint when you [create or edit a pool](https://developers.cloudflare.com/load-balancing/pools/create-pool/#create-a-pool). This will enable Cloudflare load balancers to use the correct tunnel and securely reach the private IP endpoints.

The specific configuration will vary depending on your use case. Refer to the following steps to understand the workflow.

1. [Create the Load Balancing monitor](https://developers.cloudflare.com/load-balancing/monitors/create-monitor/) according to your needs.
2. [Create the pool](https://developers.cloudflare.com/load-balancing/pools/create-pool/) specifying your private IP addresses and corresponding virtual networks.

Note

* Currently, Cloudflare does not support entering the same endpoint IP addresses more than once, even when using different virtual networks.
* All endpoints with private IPs must have `virtual_network_id` specified.

1. [Create the load balancer](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/), specifying the pool and monitor you created in the previous steps, as well as the desired [global traffic steering policies](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/) and [custom rules](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/).

Spectrum limitations

If you will use the load balancer with [Spectrum](https://developers.cloudflare.com/spectrum/), consider the applicable [limitations](https://developers.cloudflare.com/load-balancing/additional-options/spectrum/#limitations) on load balancing and monitoring options.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/private-network/","name":"Private Network Load Balancing"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/private-network/public-to-tunnel/","name":"Set up Private Network Load Balancing for Public traffic to Tunnel"}}]}
```

---

---
title: Set up Private Network Load Balancing with Client-to-Tunnel
description: Load balance WARP client traffic to private origins via Tunnel.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Set up Private Network Load Balancing with Client-to-Tunnel

You can use Private Network Load Balancing to distribute Cloudflare One Client traffic to private hostnames and IPs connected via [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/).

For example, assume you have an internal application running in two data centers, and you want Cloudflare One Client users to access the application from the data center closest to their geographic location. A typical load balancing configuration is shown in the following diagram:

graph LR
    W[WARP clients] --> C{Private load balancer <br> 100.112.0.0}
    C -- Tunnel 1 --> cf1
    C -- Tunnel 2 --> cf2
		subgraph D2[Data center 2]
			cf2@{ shape: processes, label: "cloudflared" }
			subgraph F[Pool 2]
					S3["Endpoint <br> 10.0.0.1 (VNET-2)"]
					S4["Endpoint <br> 10.0.0.2 (VNET-2)"]
			end
			cf2-->S3
			cf2-->S4
		end
		subgraph D1[Data center 1]
			cf1@{ shape: processes, label: "cloudflared" }
			subgraph E[Pool 1]
					S1["Endpoint <br> 10.0.0.1 (VNET-1)"]
					S2["Endpoint <br> 10.0.0.2 (VNET-1)"]
			end
			cf1-->S1
			cf1-->S2
		end

		style E stroke-width:2px,stroke-dasharray: 5 5
		style F stroke-width:2px,stroke-dasharray: 5 5

The components in the diagram include:

* **cloudflared**: Each data center is connected to Cloudflare with its own Cloudflare Tunnel. `cloudflared` installs on one or [more](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/tunnel-availability/#cloudflared-replicas) host machines in the network.
* **Private load balancer IP**: End users connect to the application using the load balancer's IP address. This can either be a Cloudflare-assigned IP in `100.112.0.0/16` or a custom `/32` IP in an [RFC 1918 range ↗](https://datatracker.ietf.org/doc/html/rfc1918).
* **Load balancer pool**: The load balancer is configured with one [pool](https://developers.cloudflare.com/load-balancing/understand-basics/load-balancing-components/#pools) per tunnel.
* **Load balancer endpoint**: A pool contains one or more endpoints, where each endpoint is a server behind `cloudflared` that is running the application. If your servers have overlapping IPs, you can assign a distinct [virtual network (VNET)](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/private-net/cloudflared/tunnel-virtual-networks/) per tunnel so that Load Balancer can deterministically route requests to the correct endpoint.

Note

Load Balancing does not currently support [private hostname routing](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/private-net/cloudflared/connect-private-hostname/). Load balancing endpoints must be defined using an IP address and virtual network (for example, `10.0.0.1 (VNET-1)`).

## Prerequisites

* Your endpoint IP addresses route through Cloudflare Tunnel. To learn how to connect your private network, refer to [Connect an IP/CIDR](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/private-net/cloudflared/connect-cidr/).

## 1\. Create load balancer pools

Load balancer pools are logical groupings of endpoints, typically organized by physical datacenter or geographic region. The endpoints in the pool are the destinations where traffic is ultimately routed.

Pools can be created using either the Cloudflare dashboard or the API.

* [ Dashboard ](#tab-panel-9184)
* [ API ](#tab-panel-9185)

To create a pool using the dashboard, refer to the [Create a pool](https://developers.cloudflare.com/load-balancing/pools/create-pool/#create-a-pool) documentation.

Endpoint IP address limitations

* All endpoints with private IPs must have a [virtual network (VNET)](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/private-net/cloudflared/tunnel-virtual-networks/) specified. If you did not select a VNET when adding a Cloudflare Tunnel route, the endpoint will be assigned to the `default` VNET.
* A pool cannot have multiple endpoints with the same IP address, even when using different virtual networks. You can assign endpoints with overlapping IPs to different pools, as shown in the [example diagram](#%5Ftop).

To get a list of your current virtual networks, use the [List virtual networks](https://developers.cloudflare.com/api/resources/zero%5Ftrust/subresources/networks/subresources/virtual%5Fnetworks/methods/list/) API operation.

Enable virtual/private IP support by adding the `virtual_network_id` field to the `origins` in your API request. Refer to the [Cloudflare Load Balancer API documentation](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/create/) for more information on how to create a pool using the API.

The following example adds a Cloudflare Tunnel endpoint to an existing Load Balancer pool:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Load Balancing: Monitors and Pools Write`

Patch Pool

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/load_balancers/pools/$POOL_ID" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "origins": [

        {

            "name": "server-1",

            "address": "10.0.0.1",

            "enabled": true,

            "weight": 1,

            "virtual_network_id": "a5624d4e-044a-4ff0-b3e1-e2465353d4b4"

        }

    ]

  }'


```

## 2\. Create a private load balancer

1. In the Cloudflare dashboard, go to the **Load Balancing** page.  
[ Go to **Load Balancing** ](https://dash.cloudflare.com/?to=/:account/load-balancing)
2. Select **Create a Load Balancer**.
3. Select **Private Load Balancer**.
4. On the next step you can choose to associate this load balancer with either:  
   * A Cloudflare-assigned IP from the `100.112.0.0/16` range  
   * A custom `/32` IP in an [RFC 1918 range ↗](https://datatracker.ietf.org/doc/html/rfc1918)
5. Add a descriptive name to identify your load balancer.
6. Proceed through the setup.

After completing the setup, you will be redirected to the Load Balancing dashboard. You can locate your load balancer using the search bar or by filtering for **Private** load balancers. Be sure to note the load balancer IP as it will be required in the following steps.

## 3\. Route the load balancer IP through the Cloudflare One Client

In order for Cloudflare One Clients to connect to your load balancer, the load balancer's IP address must route through the WARP tunnel in your [Split Tunnel settings](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/cloudflare-one-client/configure/route-traffic/split-tunnels/).

1. In the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), go to **Zero Trust** \> **Team & Resources** \> **Device profiles**.
2. Find the [device profile](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/cloudflare-one-client/configure/device-profiles/) you would like to modify and select **Edit**.
3. Under **Split Tunnels**, check whether your [Split Tunnels mode](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/cloudflare-one-client/configure/route-traffic/split-tunnels/#change-split-tunnels-mode) is set to **Exclude** or **Include**.
4. Select **Manage**. Depending on the mode:  
   * **Exclude mode**: Delete the IP range that contains your load balancer IP. For example, if your load balancer has a Cloudflare-assigned CGNAT IP, delete `100.64.0.0/10`. We recommend [adding back the IPs](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/private-net/cloudflared/connect-cidr/#3-route-private-network-ips-through-the-cloudflare-one-client) that are not being used by your load balancer.  
   Note  
   Some IPs in the `100.64.0.0/10` range may be reserved for other Zero Trust services such as Gateway initial resolved IPs or WARP CGNAT IPs. These IPs should remain deleted from the Exclude list.  
   * **Include mode**: Add your load balancer IP.

Cloudflare One Client traffic can now reach your private load balancer. For example, if your load balancer points to a web application, you can test by running `curl <load-balancer-IP>` from the device. This traffic will be distributed over Cloudflare Tunnel to your private endpoints according to your configured steering method.

## 4\. (Optional) Assign a hostname to the load balancer

If you want your load balancer and its endpoints to be transparently accessible to users via a hostname, you can create a Gateway DNS [Override policy](https://developers.cloudflare.com/cloudflare-one/traffic-policies/dns-policies/#override) that maps the hostname to the load balancer's IP address. This ensures that traffic destined for the hostname resolves to the correct IP.

1. In the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), go to **Zero Trust** \> **Traffic policies** \> **Firewall policies** \> **DNS**.
2. Select **Add a policy**.
3. In **Traffic**, create an expression where the **Selector** equals `Host`, the **Operator** equals `is`, and **Value** is the hostname you wish to associate with your load balancer. For example,  
| Selector | Operator | Value              |  
| -------- | -------- | ------------------ |  
| Host     | is       | app.internal.local |
4. Set the **Action** to _Override_.
5. In **Override Hostname**, enter your private load balancer IP (for example, `100.112.0.0`).

Requests to the hostname will now resolve to your private load balancer.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/private-network/","name":"Private Network Load Balancing"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/private-network/warp-to-tunnel/","name":"Set up Private Network Load Balancing with Client-to-Tunnel"}}]}
```

---

---
title: Additional configuration
description: Additional load balancing features and integrations.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Additional configuration

Beyond [creating a simple load balancer](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/), you may want to further customize how your load balancer routes traffic or integrate your load balancer with other Cloudflare products.

## Customize load balancer behavior

* Route traffic according to characteristics of each request by [creating custom rules](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/)
* Protect at-risk endpoints from reaching failover by [setting up load shedding](https://developers.cloudflare.com/load-balancing/additional-options/load-shedding/)
* Take endpoints out of rotation for [planned maintenance](https://developers.cloudflare.com/load-balancing/additional-options/planned-maintenance/)

## Integrate with other Cloudflare products

* Bring load balancing to your TCP or UDP applications with [Cloudflare Spectrum](https://developers.cloudflare.com/load-balancing/additional-options/spectrum/)
* Further secure endpoint access with [Cloudflare Tunnel](https://developers.cloudflare.com/load-balancing/additional-options/cloudflare-tunnel/)

## Integrate with 3rd parties

* Increase visibility by [sending health monitor notifications to PagerDuty](https://developers.cloudflare.com/load-balancing/additional-options/pagerduty-integration/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/additional-options/","name":"Additional configuration"}}]}
```

---

---
title: Additional DNS records
description: Use additional DNS records with load balancers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Additional DNS records

In addition to load balancing between DNS records used for IP resolution — `A`, `AAAA`, and `CNAME` records — Enterprise customers can also load balance between **MX** and **SRV** records.

## MX records

To load balance between multiple mail servers:

1. Make sure you have the [required DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/email-records/#send-and-receive-email) for your mail servers.
2. [Create a monitor](https://developers.cloudflare.com/load-balancing/monitors/create-monitor/) with a **Type** of _SMTP_.
3. [Create a pool](https://developers.cloudflare.com/load-balancing/pools/create-pool/) with your mail servers and attach the newly created monitor.
4. [Create a load balancer](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/) that includes your newly created pools. Since it will forward SMTP traffic, the load balancer should be [unproxied (DNS-only)](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/#dns-only-load-balancing).

## SRV records

To load balance between different **SRV** records, which contain significantly more information than many other DNS records:

1. [Create your SRV records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records).
2. [Create a monitor](https://developers.cloudflare.com/load-balancing/monitors/create-monitor/) with a **Type** of _UDP-ICMP_ or _TCP_.
3. [Create a pool](https://developers.cloudflare.com/load-balancing/pools/create-pool/) with your various SRV records and attach the newly created monitor.
4. [Create a load balancer](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/) that includes your newly created pools. This load balancer should be [unproxied (DNS-only)](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/#dns-only-load-balancing).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/additional-options/","name":"Additional configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/additional-options/additional-dns-records/","name":"Additional DNS records"}}]}
```

---

---
title: Cloudflare Tunnel (published applications)
description: Load balance traffic to Cloudflare Tunnel applications.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare Tunnel (published applications)

Cloudflare Tunnel (formerly Argo Tunnel) establishes a secure outbound connection which runs in your infrastructure to connect the applications and machines to Cloudflare.

For more details on how to use Load Balancing with Cloudflare Tunnel and public hostnames, refer to [Route tunnel traffic using a load balancer](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/routing-to-tunnel/public-load-balancers/). For using private IPs instead, refer to [Set up private IPs with Tunnel](https://developers.cloudflare.com/load-balancing/private-network/warp-to-tunnel/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/additional-options/","name":"Additional configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/additional-options/cloudflare-tunnel/","name":"Cloudflare Tunnel (published applications)"}}]}
```

---

---
title: DNS persistence
description: Maintain consistent DNS responses for load balanced hostnames.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNS persistence

This guide explains how to achieve DNS persistence when using Cloudflare Load Balancing, similar to functionality provided by traditional DNS-based load balancers.

DNS persistence ensures that subsequent DNS requests from the same local DNS server receive the same IP address. This is useful for applications that require session consistency, such as VPN connections or authentication systems.

Cloudflare Load Balancing can achieve DNS persistence using different configuration approaches for DNS-only load balancing.

---

## DNS-only load balancing persistence

For DNS-only load balancing, Cloudflare offers three methods to achieve DNS persistence:

### Method 1: Geo-steering based on PoP location (Recommended)

This method uses geographic steering based on the Cloudflare Point of Presence (PoP) that receives the DNS request.

#### Configuration steps

1. Create a pool for each endpoint. Do not apply load shedding to either pool.
2. Create a DNS-only load balancer and add both pools. Ensure `pool_1` is ordered before `pool_2`.
3. Under **Traffic Steering**, select **Geo Steering**.
4. Create a geo-steering rule for a region (for example, **Eastern North America**) and select the same pools but in reverse order (`pool_2` first, then `pool_1`).
5. Use **Never prefer ECS** and **PoP location** to determine the source of the request.

#### How it works

All requests received at Cloudflare PoPs in the specified region are sent to one endpoint, while requests from other regions are sent to the other endpoint.

#### Why this is recommended

Using the Cloudflare PoP that received the request as criteria for steering is more stable than IP hashing or splitting IP space, as it is not affected by recursive DNS providers using different egress IPs.

### Method 2: Load shedding with IP hash

This method uses load shedding to distribute traffic based on the source IP address of the recursive DNS resolver.

#### Configuration steps

1. Create a pool for each endpoint (for example, `pool_1` with `endpoint_1` and `pool_2` with `endpoint_2`).
2. On the first pool, select **Hash** under **Endpoint Steering**.
3. Configure **Load Shedding**:  
   * **Policy**: IP Hash  
   * **Shed %**: 50% (to split traffic evenly between two pools)
4. Create a DNS-only load balancer and add both pools. Ensure `pool_1` is ordered before `pool_2`.
5. Do not configure additional traffic steering or rules.

#### How it works

This configuration sheds half of the requests to the second pool using an IP hash and respects session affinity per source IP of the recursive resolver.

#### Limitations

Some recursive DNS providers (like Google DNS 8.8.8.8 or Quad9 9.9.9.9) may use different egress IPs randomly, which can reduce persistence stability.

### Method 3: Custom rules with IP source filtering

This method uses custom rules to split traffic based on IP address ranges.

#### Configuration steps

1. Create a pool for each endpoint. Do not apply load shedding to either pool.
2. Create a DNS-only load balancer and add both pools. Ensure `pool_1` is ordered before `pool_2`.
3. Do not configure traffic steering.
4. Create a **Custom Rule** with:  
   * **Field**: IP Source Address  
   * **Operator**: is in  
   * **Value**: A subset of IP space (for example, `0.0.0.0/1` for the lower half of IPv4 space)
5. For the rule action, choose **Override** \> **Endpoints** and set the pools in reverse order (`pool_2`, `pool_1`).

#### How it works

Traffic with source IPs in the lower half of IPv4 space is sent to one endpoint, while traffic in the upper half is sent to the other endpoint.

#### Limitations

Similar to Method 2, this approach may be less stable with recursive DNS providers that use varying egress IPs.

---

## Related resources

* [Session Affinity](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/)
* [Load Shedding](https://developers.cloudflare.com/load-balancing/additional-options/load-shedding/)
* [Geo Steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/geo-steering/)
* [Custom Rules](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/additional-options/","name":"Additional configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/additional-options/dns-persistence/","name":"DNS persistence"}}]}
```

---

---
title: Load Balancing with the China Network
description: Use Load Balancing with the China Network.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Load Balancing with the China Network

## Prerequisites

To enable load balancers to be deployed to the [China Network](https://developers.cloudflare.com/china-network/), your zone will need to meet the following two criteria:

1. A valid [ICP license](https://developers.cloudflare.com/china-network/concepts/icp/) for the zone in question.
2. The zone must be provisioned with access to the China Network.

Once these two criteria are met, any newly created load balancer will be automatically deployed to the China Network. When choosing a region for a pool's health checks, `China` is now available to be selected in both the dashboard and API.

You can also create a load balancer by sending a `POST` request to the following endpoint. To deploy to the China Network with the API, the `networks` array in the API call must contain `jdcloud` as a value in addition to `cloudflare`. Refer to the [Cloudflare API documentation](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/create/) for details on the required fields and their formats.

Terminal window

```

https://api.cloudflare.com/client/v4/zones/{zone_id}/load_balancers


```

## Limitations

Load balancers deployed to the China Network currently have the following limitations:

* Only cookie-based session affinity is supported.
* Private network off-ramps (Tunnel, GRE, IPsec) are not supported.
* Private Network Load Balancing is not available on the China Network.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/additional-options/","name":"Additional configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/additional-options/load-balancing-china/","name":"Load Balancing with the China Network"}}]}
```

---

---
title: Custom load balancing rules
description: Customize load balancing behavior with custom rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Custom load balancing rules

Custom load balancing rules let you customize the behavior of your load balancer based on the characteristics of a request.

For example, you can use URL-based routing, or create a rule that selects a pool based on the URI path of an HTTP request.

## How custom rules work

As with [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/), each load balancing custom rule is a combination of two elements: an [expression](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/expressions/) and an [action](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/actions/). Expressions define the criteria for an HTTP request to trigger an action. The action tells Cloudflare how to handle the request.

You can [create Load Balancing rules](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/create-rules/) whenever you create or edit a load balancer in **Load Balancing**.

When building expressions for Load Balancing rules, refer to [Supported fields and operators](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/reference/) for definitions and usage.

## Availability

By default, non-Enterprise customers have **one** Load Balancing rule **per load balancer hostname**. For more rules, upgrade to [Enterprise ↗](https://www.cloudflare.com/enterprise/).

## Limitations

At the moment, you cannot use Load Balancing rules with [Cloudflare Spectrum](https://developers.cloudflare.com/spectrum/about/load-balancer/).

Custom load balancing rules are incompatible with [Geo steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/geo-steering/). As a result, any custom rule applied to Geo-steered load balancers will not function as expected.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/additional-options/","name":"Additional configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/additional-options/load-balancing-rules/","name":"Custom load balancing rules"}}]}
```

---

---
title: Actions
description: Actions available in custom load balancing rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Actions

Add **actions** to customize how your load balancer responds to certain HTTP requests.

Each load balancing rule includes one or more actions.

## Supported Actions

This table lists the actions available for Load Balancing rules. For a walkthrough, refer to [Create Load Balancing rules](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/create-rules/).

| Action           | Options             | Description                                                                                                                                                                                             |
| ---------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| _Fixed response_ | _N/A_               | Respond to the request with an HTTP status code and an optional message.                                                                                                                                |
| _Override_       | _Session affinity_  | Set the [session affinity](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/) for the request. You can customize cookie behavior and session time-to-live (TTL).     |
| _Override_       | _Load balancer TTL_ | Customize the load balancer session time-to-live (TTL).                                                                                                                                                 |
| _Override_       | _Steering policy_   | Update the [steering policy](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/) associated with your load balancer.                                |
| _Override_       | _Fallback pool_     | Update the [fallback pools](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/standard-options/#off---failover) associated with your load balancer. |
| _Override_       | _Pools_             | Update the [pools](https://developers.cloudflare.com/load-balancing/pools/) associated with your load balancer.                                                                                         |
| _Override_       | _Region pools_      | Update the [region pools](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/geo-steering/) associated with your load balancer.                      |
| _Override_       | _Terminates_        | Stop processing Load Balancing rules and apply the current load balancing logic to the request.                                                                                                         |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/additional-options/","name":"Additional configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/additional-options/load-balancing-rules/","name":"Custom load balancing rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/load-balancing/additional-options/load-balancing-rules/actions/","name":"Actions"}}]}
```

---

---
title: Create custom rules
description: Create custom rules for load balancing behavior.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Create custom rules

Create and manage [Load Balancing rules](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/) in the **Custom Rules** page, which is part of the Create/Edit Load Balancer workflow found in **Traffic** in the dashboard.

---

## Prerequisites

* **Understand whether Cloudflare proxies your traffic**: Depending on the [proxy status](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/) of your traffic, you may have access to different fields for your load balancing rules. For more details, refer to [Supported fields and expressions](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/reference/).

---

## Example Workflow

1. In the Cloudflare dashboard, go to the **Load Balancing** page.  
[ Go to **Load Balancing** ](https://dash.cloudflare.com/?to=/:account/load-balancing)
2. Edit an existing load balancer or [create a new load balancer](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/).
3. From the Load Balancer workflow, select **Custom Rules**.
4. Select **Create Custom Rule**.
5. In the **Field** drop-down list, choose an HTTP property. For more details, refer to [Supported fields](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/reference/).
6. In the **Operator** drop-down list, choose an operator. For more details, refer to [Operators](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/reference/#operators-and-grouping-symbols).
7. Enter the value to match. When the field is an ordered list, **Value** is a drop-down list. Otherwise, **Value** is a text input.
8. (Optional) To create a compound expression using logical operators, select **And** or **Or**.
9. For an action, choose **Respond with fixed response** or **Override** and enter additional details. For a full list of actions, refer to [Actions](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/actions/).
10. (Optional) Select **Add another override**.
11. After you create your rule, select **Save and Deploy** or **Save as Draft**.
12. Select **Next** and review your changes.
13. Select **Save** to confirm.

Warning

To save a new load balancer rule, make sure to save both the rule **and** the overall load balancer configuration.

Note

In general, for non-terminating actions, the last change made by rules within the same [phase](https://developers.cloudflare.com/ruleset-engine/about/phases/) will win (later rules can overwrite changes made by previous ones). However, for [terminating actions](https://developers.cloudflare.com/ruleset-engine/rules-language/actions/), such as Block, Redirect, or any of the challenge actions, rule evaluation will stop and the action is executed immediately.

Load Balancer Custom Rules override the default Load Balancer settings, including pool and origin selection. These are non-terminating actions, so the last rule applied will override any prior rules.

## Example use case

### URL-based routing

If you want to host `example.com/blog` separately from your main website, for example, use the following custom rule.

**When incoming requests match**:

| Field    | Operator | Value |
| -------- | -------- | ----- |
| URI Path | contains | /blog |

**Then**:

| Action    | Options | Value          |
| --------- | ------- | -------------- |
| Overrides | Pools   | <BLOG\_SERVER> |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/additional-options/","name":"Additional configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/additional-options/load-balancing-rules/","name":"Custom load balancing rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/load-balancing/additional-options/load-balancing-rules/create-rules/","name":"Create custom rules"}}]}
```

---

---
title: Expressions
description: Expression syntax for custom load balancing rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Expressions

[Load Balancing rules](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/) use two kinds of expressions:

* [Simple expressions](#simple-expressions) compare a value from an HTTP request to a value defined in the expression. A simple expression is identified by the presence of a **comparison operator** (_equals_ or _less than_, for example).
* [Compound expressions](#compound-expressions) combine two or more simple expressions into a single expression. Compound expression contains a **logical operator** (_and_, _or_, for example). With compound expressions you can tailor rules to specific use cases with a high degree of accuracy and precision.

---

## Simple expressions

Simple expressions are composed of three elements:

1. A **field** that represents a property of an HTTP request.
2. A representative **value** for that field which Cloudflare compares to the actual request value.
3. A **comparison operator**, which specifies how the value defined in the expression must relate to the actual value from the request for the operator to return `true`.

When the comparison operator returns `true`, the request matches the expression.

This example expression returns true when a request URI path contains `/content`:

```

(http.request.uri.path contains "/content")


```

In general, simple expressions use this pattern:

```

<field> <operator> <value>


```

For more details, refer to [Supported fields and operators](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/reference/).

---

## Compound expressions

A compound expression uses a **logical operator** (_and_, _or_, for example) to combine two or more expressions. Compound expressions allow you to build complex statements within a single expression.

The example expression below returns true when both the HTTP request URI path contains `/content` and the query string contains `webserver`:

```

(http.request.uri.path contains "/content")

and (http.request.uri.query contains "webserver")


```

In general, compound expressions use this pattern:

```

<expression> <logical operator> <expression>


```

A compound expression can be an operand of a logical operator. This allows multiple operators to construct a compound expression from many individual expressions.

For more details, refer to [Supported fields and operators](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/reference/).

---

## Working with expressions

The Expression Builder’s visual interface allows you to build expressions without worrying about field names and syntax.

By comparison, the Expression Editor is text only, but it supports advanced features not available in the builder.

### Expression Builder

Compound expressions are easier to scan when displayed in the Expression Builder’s visual interface, and the Expression Preview is a great reference for learning to write more advanced expressions.

This Expression Builder screenshot shows the example compound expression described earlier. Compound expressions are easier to scan when displayed in the Expression Builder’s visual interface.

![Example rule configuration visible in the Expression Builder](https://developers.cloudflare.com/_astro/rules-builder-1.CBdNVOoP_ZXG1w7.webp) 

The **Expression Preview** displays the expression in text:

```

(http.request.uri.path contains "/content")

and (http.request.uri.query contains "webserver")


```

For a walkthrough, refer to [Creating Load Balancing rules](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/create-rules/).

### Expression Editor

The Expression Editor is a text-only interface for creating Load Balancing expressions. Although it lacks the visual simplicity of the Expression Builder, the Expression Editor supports advanced features such as support for grouping symbols (parentheses).

To access the Expression Editor in the **Traffic** app, click **Edit expression** in the **Create Custom Rule** dialog.

To return to the builder, click **Use expression builder**.

### Rules lists

Load Balancing Custom Rules does not support IP list operators.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/additional-options/","name":"Additional configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/additional-options/load-balancing-rules/","name":"Custom load balancing rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/load-balancing/additional-options/load-balancing-rules/expressions/","name":"Expressions"}}]}
```

---

---
title: Supported fields and operators
description: Fields and operators for load balancing rule expressions.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Supported fields and operators

The fields that are supported by load balancing rules depend on whether Cloudflare proxies the traffic going through your load balancer or not.

If you use the wrong set of fields, you might see unexpected behaviors. For best results, use the fields associated with your traffic's [proxy status](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/).

Also, some Load Balancing rules fields are available on the Expression Builder - as described in [Load Balancing expressions](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/expressions/#working-with-expressions) \- while others can only be configured manually, via API or [Expression Editor](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/expressions/#expression-editor)

## Expression Builder field sets

Consider the following table to know how the fields available in the [Expression Builder](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/expressions/#expression-builder) are grouped.

| Field Set                                                                     | Section in Expression Builder | Description                                                                      |
| ----------------------------------------------------------------------------- | ----------------------------- | -------------------------------------------------------------------------------- |
| [Fields supported regardless of proxy](#fields-supported-regardless-of-proxy) | BOTH                          | Values that are always accessible regardless of the load balancer proxy status.  |
| [Proxied-only fields](#proxied-only-fields)                                   | PROXIED ONLY                  | Values accessible only when the load balancer is proxied.                        |
| [Unproxied-only fields](#unproxied-only-fields)                               | NON-PROXIED ONLY              | Values accessible only when the load balancer is not proxied (DNS-only traffic). |

![Choose load balancer fields based on the proxy status header](https://developers.cloudflare.com/_astro/proxy-status.DIPDmp1m_128h8u.webp) 

## Fields supported regardless of proxy

Regardless of your traffic [proxy status](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/), Load Balancing rules can access values for the following fields:

| Field                         | Name in Expression Builder | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| ----------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cf.load\_balancer.nameBytes   | Load Balancer Name         | Represents the name of the load balancer executing these rules.Example value:lb.example.com                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| cf.load\_balancer.regionBytes | Load Balancer Region       | Provides the [region name](https://developers.cloudflare.com/load-balancing/reference/region-mapping-api/#list-of-load-balancer-regions) of the data center processing the request.Example value:ENAM                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ip.srcIP address              | IP Source Address          | If proxied, this field provides the client TCP IP address, which may be adjusted to reflect the actual address of the client by using HTTP headers such as X-Forwarded-For or X-Real-IP.If unproxied (DNS-only), this field provides the ECS source address, if available. If not available, it provides the client resolver IP address.**Deprecation Warning:** In the future, this field will always be set to the client resolver IP address for unproxied requests. To check for the presence of ECS and use the ECS IP, see the fields [dns.rr.opt.client](#field-dns-rr-opt-client) and [dns.rr.opt.client.addr](#field-dns-rr-opt-client-addr), respectively.Example value:1.2.3.4 |
| ip.src.asnumNumber            | AS Number                  | The 16-bit or 32-bit integer representing the Autonomous System (AS) number associated with the client IP address.Example value:13335                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |

## Proxied-only fields

If your traffic is proxied through Cloudflare, you have access to all the fields listed under [Fields supported regardless of proxy](#fields-supported-regardless-of-proxy) in addition to the following fields:

Many of these fields are referenced from the [Rules language documentation](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/).

| Field                                                                                                                                                       | Name in Expression Builder                                                                                                                     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [http.cookie](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.cookie/)String                                          | ([Manual entry only](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/expressions/#expression-editor)) | Represents the entire cookie as a string.Example value:session=8521F670545D7865F79C3D7BEDC29CCE;-background=light                                                                                                                                                                                                                                                                                                                                                                         |
| [http.host](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.host/)String                                              | ([Manual entry only](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/expressions/#expression-editor)) | Represents the hostname used in the full request URI.Example value:[www.example.org ↗](http://www.example.org)                                                                                                                                                                                                                                                                                                                                                                            |
| [http.referer](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.referer/)String                                        | ([Manual entry only](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/expressions/#expression-editor)) | Represents the HTTP Referer request header, which contains the address of the web page that linked to the currently requested page.Example value:Referer: htt­ps://developer.example.org/en-US/docs/Web/JavaScript                                                                                                                                                                                                                                                                        |
| [http.request.headers](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.request.headers/)Map<Array<String>>            | Header                                                                                                                                         | Represents HTTP request headers as a Map (or associative array).The keys of the associative array are the names of HTTP request headers **converted to lowercase**.When there are repeating headers, the array includes them in the order they appear in the request.__Decoding:_ no decoding performed_Whitespace:_ preserved_Non-ASCII:_ preservedExample:any(http.request.headers\["content-type"\]\[\*\] == "application/json")Example value:{"content-type": \["application/json"\]} |
| [http.request.method](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.request.method/)String                          | Request Method                                                                                                                                 | Represents the HTTP method, returned as a string of uppercase characters.Example value:GET                                                                                                                                                                                                                                                                                                                                                                                                |
| [http.request.timestamp.sec](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.request.timestamp.sec/)Integer           | Timestamp                                                                                                                                      | Represents the timestamp when Cloudflare received the request, expressed as Unix time in seconds. This value is 10 digits long.Example value:1484063137                                                                                                                                                                                                                                                                                                                                   |
| [http.request.uri](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.request.uri/)String                                | URI                                                                                                                                            | Represents the URI path and query string of the request.Example value:/articles/index?section=539061&expand=comments                                                                                                                                                                                                                                                                                                                                                                      |
| [http.request.uri.args](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.request.uri.args/)Map<Array<String>>          | ([Manual entry only](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/expressions/#expression-editor)) | Represents the HTTP URI arguments associated with a request as a Map (associative array).When an argument repeats, then the array contains multiple items in the order they appear in the request.The values are not pre-processed and retain the original case used in the request._Decoding:_ no decoding performed_Non-ASCII:_ preservedExample:any(http.request.uri.args\["search"\]\[\*\] == "red+apples")Example value:{"search": \["red+apples"\]}                                 |
| [http.request.uri.args.names](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.request.uri.args.names/)Array<String>   | ([Manual entry only](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/expressions/#expression-editor)) | Represents the names of the arguments in the HTTP URI query string. The names are not pre-processed and retain the original case used in the request.When a name repeats, the array contains multiple items in the order that they appear in the request._Decoding:_ no decoding performed_Non-ASCII:_ preservedExample:any(http.request.uri.args.names\[\*\] == "search")Example value:\["search"\]                                                                                      |
| [http.request.uri.args.values](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.request.uri.args.values/)Array<String> | ([Manual entry only](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/expressions/#expression-editor)) | Represents the values of arguments in the HTTP URI query string. The values are not pre-processed and retain the original case used in the request. They are in the same order as in the request.Duplicated values are listed multiple times._Decoding:_ no decoding performed_Non-ASCII:_ preservedExample:any(http.request.uri.args.values\[\*\] == "red+apples")Example value:\["red+apples"\]                                                                                         |
| [http.request.uri.path](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.request.uri.path/)String                      | URI Path                                                                                                                                       | Represents the URI path of the request.Example value:/articles/index                                                                                                                                                                                                                                                                                                                                                                                                                      |
| [http.request.uri.query](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.request.uri.query/)String                    | URI Query                                                                                                                                      | Represents the entire query string, without the ? delimiter.Example value:section=539061&expand=comments                                                                                                                                                                                                                                                                                                                                                                                  |
| [http.request.version](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.request.version/)String                        | HTTP Version                                                                                                                                   | Represents the version of the HTTP protocol used. Use this field when you require different checks for different versions.Example Values:HTTP/1.1HTTP/3                                                                                                                                                                                                                                                                                                                                   |

## Unproxied-only fields

If your traffic is not proxied through Cloudflare, you have access to all the fields listed under [Fields supported regardless of proxy](#fields-supported-regardless-of-proxy) in addition to the following fields:

| Field                        | Name in Expression Builder                                                                                                                     | Description                                                                                                                                                      |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| dns.qry.nameBytes            | Query Name                                                                                                                                     | Represents the query name asked.Example value:example.com.                                                                                                       |
| dns.qry.name.lenInteger      | Query Name Length                                                                                                                              | Represents the length in bytes of the query name.Example value:123                                                                                               |
| dns.qry.quBoolean            | Question                                                                                                                                       | When true, this field indicates that the received DNS message was a question.                                                                                    |
| dns.qry.typeInteger          | Query Type                                                                                                                                     | Represents the numeric value of the [DNS query type](https://en.wikipedia.org/wiki/List%5Fof%5FDNS%5Frecord%5Ftypes).Example Values:1 (A record)28 (AAAA record) |
| dns.rr.opt.clientBoolean     | ([Manual entry only](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/expressions/#expression-editor)) | When true, this field indicates that the EDNS Client Subnet (ECS) address was sent with the DNS request.                                                         |
| dns.rr.opt.client.addrString | ([Manual entry only](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/expressions/#expression-editor)) | If present, this field represents the ECS address sent with the DNS request.Example value:1.2.3.0                                                                |

## Operators and grouping symbols

* **Comparison operators** specify how values defined in an expression must relate to the actual HTTP request value for the expression to return true.
* **Logical operators** combine two expressions to form a compound expression and use order of precedence to determine how an expression is evaluated.
* **Grouping symbols** allow you to organize expressions, enforce operator precedence, and nest expressions.

For examples and usage, refer to [Operators and grouping symbols](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/) in the Rules language documentation.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/additional-options/","name":"Additional configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/additional-options/load-balancing-rules/","name":"Custom load balancing rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/load-balancing/additional-options/load-balancing-rules/reference/","name":"Supported fields and operators"}}]}
```

---

---
title: Load shedding
description: Use load shedding to prevent an at-risk endpoint from becoming unhealthy and starting the failover process.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Load shedding

Use load shedding to prevent an at-risk endpoint from [becoming unhealthy](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/) and starting the failover process.

Once you configure load shedding on a pool, that pool will begin diverting traffic to other pools according to your load shedding settings and the load balancer's [steering policy](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/).

## Step 1 — Identify at-risk endpoints

Using your internal metrics, identify endpoints at risk of reaching their failure threshold.

* If your endpoint is seeing increased traffic but is not yet at risk of failure, start with [Step 2](#step-2--shed-default-traffic-from-a-pool).
* If your endpoint is about to fail, start with [Step 4](#step-4--shed-additional-traffic-optional).

## Step 2 — Shed default traffic from a pool

Once you have identified an at-risk endpoint, shed a small amount of **Default** traffic from that endpoint's pool. This traffic is not affiliated with existing [Session affinity](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/) sessions.

Configure load shedding via the [dashboard](#configure-via-dashboard) or the [API](#configure-via-api).

### Configure via dashboard

To enable load shedding for a specific pool via the dashboard:

1. Go to **Load Balancing**.
2. Select the **Pools** tab.
3. On a pool, select **Edit**.
4. Open the **Configure Load Shedding** dropdown.
5. For **Default traffic**, select a **Policy** and a **Shed %**:

Policy options

When shedding **Default traffic**, you have two **Policy** options:

* **Random**: Randomly sheds the percentage of requests specified in the _Shed %_. Distributes traffic more accurately, but may cause requests from the same IP to hit different endpoints.
* **IP hash**: Sheds the percentage of IP address hash space specified in the _Shed %_. Ensures requests from the same IP will hit the same endpoint, but may shed a significantly higher or lower percentage of requests.

For more guidance on choosing a policy, refer to [Shedding policies](#shedding-policies).

Shed %

When choosing a **Shed %**, start with a small percentage and increase gradually. Particularly if you choose the [IP hash shedding policy](#shedding-policies), you might shed more traffic than expected.

### Configure via API

To enable load shedding for a specific pool via the API, [update the values](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/update/) for the pool's `load_shedding` object.

Example request

Request

```

curl --request PATCH \

"https://api.cloudflare.com/client/v4/accounts/{account_id}/load_balancers/pools/{pool_id}" \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data-binary '{

  "load_shedding": {

    "default_percent": 20,

    "default_policy": "random",

    "session_percent": 0,

    "session_policy": "hash"

  }

}'


```

For more guidance on choosing a shedding policy, see [Shedding policies](#shedding-policies).

## Step 3 — Monitor traffic

Once you have started shedding default traffic, evaluate the effects by reviewing the [**Overview** metrics](https://developers.cloudflare.com/load-balancing/reference/load-balancing-analytics/) in Load Balancing analytics. Based on these numbers and your internal metrics, you will know whether you need to divert additional traffic from the pool.

If you see increased traffic to a pool, you may need to shed additional traffic. Pools shed a percentage of total traffic, so any increase in total traffic will also increase the traffic reaching your pool.

## Step 4 — Shed additional traffic (optional)

If you need to shed additional pool traffic:

1. Follow the steps outlined in [Step 2](#step-2--shed-default-traffic-from-a-pool).  
   * In the dashboard, increase the **Shed %** for **Default traffic** and/or **Session affinity traffic**.  
   * For the API, increase the value for `default_percent` and/or `session_percent`.

Since shedding **Session Affinity traffic** will disrupt [existing sessions](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/) and may degrade the customer experience, only enable this option if your pool is in imminent danger of becoming unhealthy or your pool has a high percentage of traffic related to existing sessions. For more guidance, see [Shedding policies](#shedding-policies).

## Step 5 — Disable load shedding

Once an endpoint is no longer at risk, remove load shedding from the pool.

To remove load shedding in the dashboard, perform the same steps as [Configure load shedding via the dashboard](#configure-via-dashboard) but set the **Shed %** to `0` for both **Default traffic** and **Session affinity traffic**.

To remove load shedding via the API, perform the same steps as [Configure load shedding via the API](#configure-via-api) but set the `load_shedding` object to `null`.

## Additional notes

### Shedding policies

For **Default traffic**, you have two choices for shedding policy.

A _Random_ policy:

* Randomly sheds the percentage of requests specified in the _Shed %_.
* Distributes traffic more accurately because it sheds at the request level.
* May cause requests from the same IP to hit different endpoints, potentially leading to cache misses, inconsistent latency, or session disruption for [DNS-only load balancers](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/#dns-only-load-balancing).

An _IP hash_ policy:

* Sheds the percentage of IP address hash space specified in the _Shed %_.
* Ensures requests from the same IP will hit the same endpoint, which will increase cache hits, provide consistent latency, and preserve sessions.
* Can over- or under-shed requests, since hashing does not guarantee a perfectly even IP distribution and individual IPs may be responsible for different percentages of your requests.

Choose a _Random_ policy when you want a more accurate distribution of raw requests and an _IP hash_ policy when you want to prevent a single IP from flapping between different endpoints.

For **Session Affinity traffic**, you can only use an _IP hash_ policy since these requests relate to existing sessions. Only increase the _Shed %_ if you are comfortable disrupting [existing sessions](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/).

### Fallback pools

If all pools within a load balancer have _Load shedding_ enabled, some traffic will go to the fallback pool. To prevent any traffic from reaching the fallback pool, ensure at least one pool within the load balancer **does not** have load shedding enabled.

### Pools in multiple load balancers

If you enable load shedding on a pool, it will shed the same percentage of traffic across all your load balancers. If you need an endpoint to shed different percentages of traffic for different load balancers, put that endpoint in multiple pools.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/additional-options/","name":"Additional configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/additional-options/load-shedding/","name":"Load shedding"}}]}
```

---

---
title: Override HTTP Host headers
description: Override HTTP Host headers sent to origin servers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Override HTTP Host headers

When your application needs specialized routing (`CNAME` setup or custom hosts like Heroku), you can customize the `Host` header used in health monitors on a per-endpoint or per-monitor level.

Important

If you set a header override on an individual endpoint, it will take precedence over a header override set on a monitor.

Also, if you configure an [Origin Rule](https://developers.cloudflare.com/rules/origin-rules/) that overrides the hostname and set up a header override in your Load Balancer configuration, the Load Balancer configuration will take precedence over the Origin Rule hostname override.

## Per endpoint Host header override

To balance traffic across multiple hosts, add `Host` headers to individual endpoints within the same pool.

For example, you might have a pool with endpoints hosted in multiple AppEngine projects or Amazon S3 buckets. You also might want to set up specific failover endpoints within a pool.

Since these examples require specific hostnames per endpoint, your load balancer will not properly route traffic _without_ a `Host` header override.

If you need an endpoint `Host` header override, add it when [creating](https://developers.cloudflare.com/load-balancing/pools/create-pool/) or editing a pool. For security reasons, this header must meet one of the following criteria:

* Is a subdomain of a zone associated with this account
* Matches the endpoint address
* Publicly resolves to the endpoint address

## Host header prioritization

If you set a header override on an individual endpoint, it will take precedence over a header override set on a monitor during health monitor requests.

For example, you might have a load balancer for `www.example.com` with the following setup:

* Pools:  
   * Pool 1:  
         * Endpoint 1 (`Host` header set to `lb-app-a.example.com`)  
         * Endpoint 2  
   * Pool 2:  
         * Endpoint 3  
         * Endpoint 4 (`Host` header set to `lb-app-b.example.com`)
* Monitor (`Host` header set to `www.example.com`)

In this scenario, health monitor requests for **Endpoint 1** would use `lb-app-a.example.com`, health monitor requests for **Endpoint 4** would use `lb-app-b.example.com`, and all other health monitor requests would default to `www.example.com`. For more information on updating your custom host configuration to be compatible with Cloudflare, see [Configure Cloudflare and Heroku over HTTPS](https://developers.cloudflare.com/support/third-party-software/others/configure-cloudflare-and-heroku-over-https/).

For a list of endpoints that override a monitor's `Host` header:

1. On a monitor, select **Edit**.
2. Select **Advanced health monitor settings**.
3. If you have endpoint overrides, you will see **Endpoint host header overrides**.
![Example configuration of endpoint host header overrides](https://developers.cloudflare.com/_astro/origin-host-header-override.CJNvqMtO_RYlCt.webp) 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/additional-options/","name":"Additional configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/additional-options/override-http-host-headers/","name":"Override HTTP Host headers"}}]}
```

---

---
title: Integrate with PagerDuty
description: Send load balancing alerts to PagerDuty.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Integrate with PagerDuty

To integrate Cloudflare health monitor notifications with PagerDuty, follow the steps outlined in PagerDuty’s [Email Integration Guide ↗](https://www.pagerduty.com/docs/guides/email-integration-guide/). If you do not have a PagerDuty account, you will first need to set that up.

PagerDuty will generate an email address that will create incidents based on emails sent to that address. For help locating that email address, refer to the [PagerDuty documentation ↗](https://www.pagerduty.com/docs/guides/email-integration-guide/).

When creating the Notifier object, configure the email to go to the PagerDuty integration email. Consequently, whenever a pool or endpoint goes down, an Incident will be created to capture it.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/additional-options/","name":"Additional configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/additional-options/pagerduty-integration/","name":"Integrate with PagerDuty"}}]}
```

---

---
title: Perform planned maintenance
description: When you change application settings or add new assets, you will likely want to make these changes on one endpoint at a time. Going endpoint by endpoint reduces the risk of changes and ensures a more consistent user experience.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Perform planned maintenance

When you change application settings or add new assets, you will likely want to make these changes on one endpoint at a time. Going endpoint by endpoint reduces the risk of changes and ensures a more consistent user experience.

To take endpoints out of rotation gradually (important for session-based load balancing), [enable endpoint drain](#gradual-rotation) on your load balancer. This option is only available for [proxied load balancers (orange-clouded)](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/).

To direct traffic away from your endpoint immediately, [adjust settings on the pool or monitor](#immediate-rotation).

Note

If you want to divert traffic from an endpoint to prevent it from becoming unhealthy, use [Load Shedding](https://developers.cloudflare.com/load-balancing/additional-options/load-shedding/) instead.

## Before you begin

Before disabling any endpoint, review the settings for any affected load balancers and pools.

If a pool falls below its **Health Threshold**, it will be considered **Unhealthy** and — depending on the load balancer setup and steering policy — a load balancer may begin routing traffic away from that pool.

## Gradual rotation

Note

Endpoint drain is only available for [proxied load balancers (orange-clouded)](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/).

With [session-based load balancing](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/), it is important to direct all requests from a particular end user to a specific endpoint. Otherwise, information about the user session — such as items in their shopping cart — may be lost and lead to negative business outcomes.

To remove an endpoint from rotation while still preserving session continuity, set up **Endpoint drain** on a load balancer:

1. On a new or existing load balancer, go to the **Hostname** step.
2. Make sure you have enabled **Session Affinity**.
3. For **Endpoint drain duration**, enter a time in seconds. If this value is less than the **Session TTL** value, you will affect existing sessions.![Example configuration of session affinity with endpoint drain](https://developers.cloudflare.com/_astro/session-affinity-3.Cv_ZhLzx_27Jgr3.webp)
4. Save your changes to the load balancer.
5. Click **Manage Pools**.
6. Disable an endpoint. Your load balancer will gradually drain sessions from that endpoint.
7. On your load balancer, expand your pools to find the disabled endpoint. You will see the estimated **Drain Time** counting down.![Example showing load balancer draining in progress](https://developers.cloudflare.com/_astro/session-affinity-4.DC0RLZtj_1H4fqz.webp)
8. When a drain is **Complete**, there are no longer any connections to that endpoint.![Example showing load balancer draining complete](https://developers.cloudflare.com/_astro/session-affinity-5.BAgwGz7x_1BV2Ow.webp)
9. Perform your required maintenance or upgrades.
10. To bring your endpoint back online, re-enable the endpoint.

## Immediate rotation

To direct traffic away from an endpoint immediately:

1. Do one of the following actions:  
   * On the endpoint's [monitor](https://developers.cloudflare.com/load-balancing/monitors/), update the monitor settings so the endpoint will fail health monitor requests, such as putting an incorrect value for the **Response Body** or **Response Code**.  
   * On the pool, disable the endpoint.  
   * On the pool, set the [endpoint weight](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/#weights) to `0` (though traffic may still reach the endpoint if it is included in multiple pools).
2. Monitor [Load Balancing Analytics](https://developers.cloudflare.com/load-balancing/reference/load-balancing-analytics/) to make sure no requests are reaching the pool.  
   * If you are using [DNS-only load balancing (gray-clouded)](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/), changes may be delayed due to DNS resolver caching.
3. Perform your required maintenance or upgrades.
4. Undo the changes you made in **Step 1**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/additional-options/","name":"Additional configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/additional-options/planned-maintenance/","name":"Perform planned maintenance"}}]}
```

---

---
title: Spectrum
description: Use Load Balancing with Spectrum for TCP and UDP traffic.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Spectrum

You can configure [Spectrum](https://developers.cloudflare.com/spectrum/) with Load Balancing to bring resiliency to your TCP or UDP based applications.

Leverage health monitors, failover, and traffic steering by selecting a load balancer as **Origin** when creating your Spectrum application.

The exact settings will vary depending on your use case. Refer to the following steps to understand the workflow.

---

## Set up

### 1\. Configure your load balancer

1. In the Cloudflare dashboard, go to the **Load Balancing** page.  
[ Go to **Load Balancing** ](https://dash.cloudflare.com/?to=/:account/load-balancing)
2. Select an account where the Load Balancing add-on is [enabled](https://developers.cloudflare.com/load-balancing/get-started/enable-load-balancing/).
3. Go to **Load Balancing** and select **Create load balancer**.
4. On the **Load Balancer Setup**, select **Public load balancer**
5. Choose the website to which you want to add this load balancer.
6. On the **Hostname** page, define the settings presented and select **Next**.  
   * Enter a **Hostname**, which is the DNS name at which the load balancer is available. For more details on record priority, refer to [DNS records for load balancing](https://developers.cloudflare.com/load-balancing/load-balancers/dns-records/).  
   Warning  
   To prevent issues with DNS resolution, the load balancer hostname should be different from the hostname (or domain) you intend to define for your Spectrum application.  
   * Keep the orange cloud icon enabled, meaning the load balancer is proxied. This refers to the [proxy mode](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/) and, with Spectrum, traffic is always proxied.  
   * Keep **Session Affinity** and **Failover across pools** disabled as these features are not supported with Spectrum.
7. On the **Add a Pool** page, define the settings presented and select **Next**.  
   * Select one or more existing pools or [create a new pool](https://developers.cloudflare.com/load-balancing/pools/create-pool/#create-a-pool) [1](#user-content-fn-1).  
   * If needed, update the [fallback pool](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/#fallback-pools) [2](#user-content-fn-2).
8. On the **Monitors** page, define the settings presented and select **Next**.  
   * Review the monitors attached to your pools.  
   * If needed, you can attach an existing monitor or [create a new monitor](https://developers.cloudflare.com/load-balancing/monitors/create-monitor/#create-a-monitor).
9. On the **Traffic Steering** page, choose an option for [Traffic steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/) and select **Next**.
10. Keep **Custom Rules** page empty as this feature is not supported with Spectrum.
11. On the **Review** page:
* Review your configuration and make any changes.  
   * If you set traffic steering to **Off**, re-order the pools in your load balancer to adjust the fallback order.  
   * If you chose to set traffic steering to Random, you can [set weights to your pools](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/standard-options/#random-steering) (via the [API](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/create/)) to determine the percentage of traffic sent to each pool.
* Choose whether to **Save as Draft** or **Save and Deploy**.

### 2\. Configure your Spectrum application

1. In the Cloudflare dashboard, go to the **Spectrum** page.  
[ Go to **Spectrum** ](https://dash.cloudflare.com/?to=/:account/:zone/spectrum)
2. Select **Create an Application**. If this is your first time using Spectrum, the **Create an Application** modal appears.
3. Select your **[Application Type](https://developers.cloudflare.com/spectrum/reference/configuration-options/#application-type)**.
4. Under **Domain**, enter the domain that will use Spectrum.
5. Under **Edge Port**, enter the port Cloudflare should use for your application.
6. Under **Origin**, select **Load Balancer**.
7. Select the load balancer you want to use from the dropdown. Disabled load balancers will not show on the **Load Balancer** menu.
8. Select **Add**.

---

## Limitations

* Load Balancing [session affinity](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/), [failover across pools](https://developers.cloudflare.com/load-balancing/understand-basics/adaptive-routing/#failover-across-pools), and [custom rules](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/) are not supported by Spectrum.
* UDP health checks are only available with public monitoring. TCP can be used with both public and private monitoring.

## Footnotes

1. Within Cloudflare, pools represent your endpoints and how they are organized. As such, a pool can be a group of several endpoints, or you could also have only one endpoint (an origin server, for example) per pool. [↩](#user-content-fnref-1)
2. A fallback pool is the pool of last resort. When all pools are disabled or unhealthy, this is where the load balancer will send traffic. [↩](#user-content-fnref-2)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/additional-options/","name":"Additional configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/additional-options/spectrum/","name":"Spectrum"}}]}
```

---

---
title: Load Balancing Reference Architecture
description: This reference architecture is for organizations looking to deploy both global and local traffic management load balancing solutions. It is designed for IT, web hosting, and network professionals with some responsibility over or familiarity with their organization's existing infrastructure.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Load Balancing Reference Architecture

**Last reviewed:**  over 2 years ago 

## Introduction

Cloudflare Load Balancing is a SaaS offering that allows organizations to host applications for a global user base while vastly reducing concerns of maintenance, failover, resiliency, and scalability. Using Cloudflare Load Balancing allows organizations to address the following challenges:

* Efficiently handling large volumes of incoming traffic, especially during unexpected surges or spikes.
* Ensuring applications and services remain accessible to users.
* Maintaining quick response times and optimal performance for all users, especially during high traffic periods.
* Adapting to changing traffic demands and ensuring the infrastructure can accommodate growth.
* Helping applications and services resist Distributed Denial of Service (DDoS) attacks.

Cloudflare Load Balancing is built on Cloudflare’s connectivity cloud, ​​a unified, intelligent platform of programmable cloud-native services that enable secure any-to-any connectivity between all networks (enterprise and Internet), cloud environments, applications, and users. It is one of the largest global networks, with data centers spanning over 330 cities and interconnection with over 13,000 network peers. It also has a greater presence in core Internet exchanges than many other large technology companies.

As a result, Cloudflare operates within \~50 ms of \~95% of the world’s Internet-connected population. And since all Cloudflare services are designed to run across every network location, all requests are routed, inspected, and filtered close to their source, resulting in strong performance and consistent user experiences.

This document describes a reference architecture for organizations looking to deploy both global and local traffic management load balancing solutions.

### Who is this document for and what will you learn?

This reference architecture is designed for IT, web hosting, and network professionals with some responsibility over or familiarity with their organization's existing infrastructure. It is useful to have some experience with networking concepts such as routing, DNS, and IP addressing, as well as basic understanding of load balancer functionality.

To build a stronger baseline understanding of Cloudflare and its load balancing solution, we recommend the following resources:

* What is Cloudflare? | [Website ↗](https://www.cloudflare.com/what-is-cloudflare/) (5 minute read) or [video ↗](https://youtu.be/XHvmX3FhTwU?feature=shared) (2 minutes)
* Solution Brief: [Cloudflare Private Network Load Balancing ↗](https://cf-assets.www.cloudflare.com/slt3lc6tev37/4mn2dtdw7TvSwCUJw8mMf5/f1fa6269f4468c432560b2c9f5ebd38a/Cloudflare%5FLocal%5FTraffic%5FManager%5FSolution%5FBrief.pdf) (5 minute read)
* Solution Brief: [Cloudflare GTM Load Balancing ↗](https://cf-assets.www.cloudflare.com/slt3lc6tev37/5OWUduF4YBKYADj3zREAX6/5241a81a3fc4ff1db7c9bade14991b23/Cloudflare%5FGlobal%5FTraffic%5FManager%5F%5FGTM%5F%5FSolution%5FBrief.pdf) (5 minute read)
* Blog: [Elevate load balancing with Private IPs and Cloudflare Tunnels: a secure path to efficient traffic distribution ↗](https://blog.cloudflare.com/elevate-load-balancing-with-private-ips-and-cloudflare-tunnels-a-secure-path-to-efficient-traffic-distribution/) (13 minutes)

Those who read this reference architecture will learn:

* How Cloudflare Load Balancing can address both Private Network Load Balancing and global traffic management use cases.
* How Cloudflare’s global network enhances the functionality of Cloudflare Load Balancing.
* The capabilities of Cloudflare Load Balancers, and how they apply to various use cases.
* The structure of Cloudflare Load Balancers and their various configurations.

## Handling dynamic workloads in modern applications

### Concepts and terminology

#### Endpoint

In this document, the term “endpoint” is any service or hardware that intercepts and processes incoming public or private traffic. Since load balancing can be used for more than just web servers, the term endpoint has been chosen to represent all possible types of origins, hostnames, private or public IP addresses, virtual IP addresses (VIPs), servers, and other dedicated hardware boxes. It could be on-premises or hosted in a public or private cloud — and could even be a third-party load balancer.

#### Steering

Steering is a load balancer’s main function — the process of handling, sending, and forwarding requests based on a set of policies. These policies generally take many factors into account, including request URL, URL path, HTTP headers, configured weights, priority, and endpoint latency, responsiveness, capacity, and load.

#### Layer 7

[Layer 7 ↗](https://www.cloudflare.com/learning/ddos/what-is-layer-7/) of the [OSI model ↗](https://www.cloudflare.com/learning/ddos/glossary/open-systems-interconnection-model-osi/), also known as the application layer, is where protocols such as SSH, FTP, NTP, SMTP, and HTTP(S) reside. When this document refers to layer 7 or layer 7 load balancers, it means HTTP(S)-based services. The Cloudflare layer 7 stack allows Cloudflare to apply services like DDoS protection, Bot Management. WAF, CDN, Load Balancing and more to a customer's website to improve performance, availability, and security.

#### Layer 4

Layer 4 of the [OSI model ↗](https://www.cloudflare.com/learning/ddos/glossary/open-systems-interconnection-model-osi/) — also called the transport layer — is responsible for end-to-end communication between two devices. Network services that operate at layer 4 can support a much broader set of services and protocols. Cloudflare’s public layer 4 load balancers are enabled by a product called Spectrum, which works as a layer 4 reverse proxy. In addition to offering load balancing, Spectrum provides protection from [DDoS attacks ↗](https://www.cloudflare.com/learning/ddos/what-is-a-ddos-attack/) and can conceal the endpoint IP addresses.

#### SSL/TLS Offloading

SSL (Secure Sockets Layer) and its successor TLS (Transport Layer Security) are cryptographic protocols used to secure connections over the Internet. SSL and TLS offloading, also known as SSL/TLS termination or SSL/TLS acceleration, is a technique used in load balancers and web servers to handle the SSL/TLS encryption and decryption process without affecting an endpoint’s performance. SSL/TLS offloading improves server performance, simplifies certificate management, and enhances scalability by offloading the resource-intensive encryption and decryption tasks to dedicated devices, helping endpoints remain dedicated to serving content and application logic.

### Challenges addressed by load balancers

Modern websites, or any applications for that matter, face three main challenges:

1. **Performance:** Ensuring that the application responds to users requests and input in a timely manner
2. **Availability:** Maintaining the uptime for the application, so it is always able to respond to user requests
3. **Scalability:** Growing, shrinking, or relocating application resources based on user behavior or demand.

#### Performance

Application performance can be affected by several factors, but the most common cause of performance issues is the amount of usage or load placed on an endpoint. An endpoint generally has a finite amount of compute resources it can provide. If too many requests arrive at once, or if the type of requests cause increased CPU/memory usage, the endpoint will respond slower or fail to respond at all.

To address these challenges, endpoints can be upgraded with more compute resources. But during idle or low-usage times, the organization ends up paying for underutilized resources. Organizations may also deploy multiple endpoints — but to seamlessly steer traffic between them, a load balancing solution is needed to make this process seamless to the end user.

Figure 1 shows how load might be distributed without a load balancer:

![Endpoint load is not distributed evenly without a load balancer](https://developers.cloudflare.com/_astro/lb-ref-arch-1.D0yttOOR_Z2ojHfp.svg "Figure 1: Endpoint performance can suffer without a load balancer")

Figure 1: Endpoint performance can suffer without a load balancer

Load balancers allow organizations to host several endpoints and portion out traffic between them, ensuring no single endpoint gets overwhelmed. The load balancer handles all incoming requests and forwards them to the appropriate endpoint. The client doesn’t need any knowledge of endpoint availability or load — it just needs to send the request to the load balancer and the load balancer handles the rest. Figure 2 shows how a load balancer can evenly distribute traffic from users across a set of endpoints.

![A load balancer helps evenly distribute requests across multiple endpoints](https://developers.cloudflare.com/_astro/lb-ref-arch-2.DiqlVt64_ZyggkG.svg "Figure 2: Load balancers help distribute load across endpoints")

Figure 2: Load balancers help distribute load across endpoints

Another performance-related issue has to do with the distance between a client and an endpoint. Whether due to the mere fact of traveling farther, or having to make more network hops, a request that travels a longer distance generally has a higher round-trip time (RTT).

RTT becomes important at scale. For example, if a client and endpoint are both located in the United States, it would be reasonable to expect a RTT of 25ms. If the client has 20 requests it needs responses to, the total time required to handle them sequentially (not including compute time) would be 500ms (20 x 25ms). And if the same client connected from the APAC region the RTT might be upwards of 150ms, resulting in an undesirable total loading time of 3000ms (20 x 150ms). (Certainly, request streaming enhancements in HTTP/2 and HTTP/3 might change this math — but in websites with dynamic or interactive content, where a response’s information is used to generate additional requests, the example still holds in general.) Figure 3 illustrates how this happens.

![Latency compounds based on the number of requests](https://developers.cloudflare.com/_astro/lb-ref-arch-3.D0FbXMvI_tMVbA.svg "Figure 3: How latency can compound and affect the total time it takes to load a resource")

Figure 3: How latency can compound and affect the total time it takes to load a resource

In the same way a load balancer can pass traffic to a less-busy endpoint, it can also pass traffic to a geographically closer endpoint, resulting in a more responsive experience for the client. Specifically, the load balancer performs a lookup of the IP address that sent the request, determines its location, and selects the closest or most region-appropriate endpoint to send it to (this is similar to functionality provided by DNS solutions like GeoDNS).

#### Availability

Service availability encompasses both unintentional and intentional downtime of endpoints behind a load balancer. Several factors can contribute to unintentional downtime, including hardware failure, software bugs, network issues, and ISP or other vendor issues. Even for the most advanced organizations, these issues are inevitable.

Load balancers solve these issues by always monitoring the health of endpoints. If an endpoint is slow to respond to a health check, or fails to respond entirely, the endpoint is marked as unhealthy. Several methods exist for monitoring, including basic health tests like ICMP (ping) and TCP connection tests. More advanced health tests can be used like issuing an HTTP GET request and ensuring a specific response code and response body are returned from the endpoint. Once an endpoint is in a degraded state, the load balancer will send fewer or no requests its way in favor of healthier endpoints. As the endpoint becomes operational again and the load balancer is able to receive responses to its health checks, the endpoint is marked as operational and has traffic steered towards it once more.

Intentional downtime comes in a few different forms, including capacity changes, hardware or infrastructure upgrades, and software updates. Load balancers gracefully remove traffic from one or more endpoints to allow for such maintenance.

#### Scale

Effective application scaling helps organizations meet customer or user demand and avoid unnecessary billing or charges. During traffic increases, organizations may need to temporarily deploy more endpoints to ensure the service stays performant and available. However, constantly having enough endpoints online to meet your maximum possible traffic could be costly regardless whether the endpoint is located on-premises or via a cloud provider like AWS, GCP, or Azure. Load balancers allow for dynamic increases or decreases in capacity by monitoring requests, connections, and latency to the endpoints.

Another type of scale to consider is geographic scale. As services grow in popularity, endpoint location becomes more important. Users in a different geographic region than an endpoint may have slower response times and receive a lower quality of service than users in the same region. As organizations deploy new endpoints in different regions, they have to decide how they want to distribute their traffic. This challenge has been met by different layers of load balancing called global traffic management (GTM) and Private Network Load Balancing. This document describes both of these in detail in the following section — but in summary, the GTM load balancer handles the initial request (typically via DNS) and then selects and steers traffic to the Private Network Load Balancer that is deployed close to endpoints in the appropriate geographic region.

### Types of traffic management

As mentioned, load balancing for global applications and services comes in two layers. The first layer is called Global Traffic Management or Manager (GTM), which may also be called Global Server Load Balancing (GSLB). The second layer is called Private Network Load Balancing, which may also be referred to as Server Load Balancing (SLB). This section will define the purpose of these different types of load balancing and how they work together.

#### Global traffic manager / global traffic management (GTM)

A Global Traffic Manager is responsible for routing requests, generally from the Internet, to the proper region or data center. Many GTM load balancers operate at the DNS layer, allowing them to:

* Resolve a DNS request to an IP address based on geographic region or physical location.
* Provide the IP of the endpoint or service closest to the client, so it can connect.

Figure 4 shows how a GTM load balancer is used to select a data center based on the client location or region.

![Global traffic management steers traffic to the proper region or data center](https://developers.cloudflare.com/_astro/lb-ref-arch-4.OnwMof7d_11aC7L.svg "Figure 4: Global traffic management load balancer overview")

Figure 4: Global traffic management load balancer overview

Global Traffic Managers can also proxy traffic and perform a variety of inspections, including reading/changing/deleting headers in HTTP requests and modifying URLs based on region or geographic location. GTM functionality is best implemented by cloud-based load balancers (like Cloudflare) since the goal is to steer traffic from anywhere in the world. Hardware load balancers exist in a single physical location, which means the further traffic originates from the load balancer, the slower the end-user experience. A cloud-based load balancer can run in many different geographic locations, helping it provide a performant solution for DNS-only, layer 4, and layer 7 contexts.

#### Private Network Load Balancing

Private Network Load Balancing steers traffic within a data center or geographic location. A Private Network Load Balancer can be responsible for load balancing, SSL/TLS offloading, content switching, and other application delivery functions. Private Network Load Balancing ensures efficient distribution of client requests across multiple endpoints to improve performance and ensure high availability. Private Network Load Balancers are usually placed inside private networks and are used to load balance publicly or privately accessible resources. In Figure 5 below, the GTM load balancer has selected the Europe data center to direct a request to the Europe data center’s Private Network Load Balancer which will then steer it to the appropriate endpoint.

![Private Network Load Balancing is responsible for steering to the final endpoint or destination](https://developers.cloudflare.com/_astro/lb-ref-arch-5.F19YgVWw_15nz5k.svg "Figure 5: Private Network Load Balancer overview")

Figure 5: Private Network Load Balancer overview

Private Network Load Balancer and their endpoints usually sit behind firewalls. But while endpoints may be protected on private networks, accessibility to the Private Network Load Balancer can be either public or private depending on deployment requirements. A Private Network Load Balancer will monitor total requests, connections, and endpoint health to ensure requests are steered towards endpoints capable of responding in a timely manner.

#### On-premises vs cloud-based load balancers

There are two main load balancer architectures:

* On-premises load balancers  
   * Typically hardware-based, but also can be virtualized or software-based  
   * Focused on maximum performance
* Cloud-based load balancers  
   * Software deployed public cloud infrastructure  
   * Handle requests closer to the originator of the request

Each approach has advantages and disadvantages. On-premises load balancers usually exist inside of private networks completely controlled by the organization. These load balancers are collocated with the endpoints they are load balancing, so latency and RTT time should be minimal. The disadvantage of these on-premises load balancers is that they are restricted to a single physical location. Which means traffic from other regions can have long RTT and high latency in responses. Also, adding another data center requires purchasing and deploying all new equipment. On-premises load balancers also typically require cloud-based load balancers for geographic traffic steering to get requests routed by a geographically local or region-appropriate data center. The advantages of cloud-based load balancers is that they can operate in almost any geographic region without concern for rack space, power, cooling, or maintenance and can scale without concern for new chassis, modules, or larger network connections. Cloud-based load balancers do however increase latency and RTT between the load balancer and the endpoints as they are not typically colocated with the endpoints they are steering traffic toward.

## Cloudflare Load Balancing architecture and design

Cloudflare has offered cloud-based GTM since 2016 and started adding Private Network Load Balancing capabilities in 2023\. This section will review the entire Cloudflare Load Balancing architecture and dive deep into the different configurations and options available. First, however, it's important to understand the benefits that Cloudflare Load Balancers have simply by running on Cloudflare’s global network.

### Inherent advantages in the Cloudflare architecture

Cloudflare Load Balancing is built on Cloudflare’s connectivity cloud, ​​a unified, intelligent platform of programmable cloud-native services that enable any-to-any connectivity between all networks (enterprise and Internet), cloud environments, applications, and users. It is one of the largest global networks, with data centers spanning over 330 cities and interconnection with over 13,000 network peers. It also has a greater presence in core Internet exchanges than many other large technology companies.

As a result, Cloudflare operates within \~50 ms of \~95% of the world’s Internet-connected population. And since all Cloudflare services are designed to run across every network location, all traffic is connected, inspected, and filtered close to the source for the best performance and consistent user experience.

Cloudflare’s load balancing solution benefits from our use of anycast technology. Anycast allows Cloudflare to announce the IP addresses of our services from every data center worldwide, so traffic is always routed to the Cloudflare data center closest to the source. This means traffic inspection, authentication, and policy enforcement take place close to the end user, leading to consistently high-quality experiences.

Using anycast ensures the Cloudflare network is well balanced. If there is a sudden increase in traffic on the network, the load can be distributed across multiple data centers – which in turn, helps maintain consistent and reliable connectivity for users. Further, Cloudflare’s large network capacity and AI/ML-optimized smart routing also help ensure that performance is constantly optimized.

By contrast, many other SaaS-based load balancing providers use Unicast routing in which a single IP address is associated with a single endpoint and/or data center. In many such architectures, a single IP address is then associated with a specific application, which means requests to access that application may have very different network routing experiences depending on how far that traffic needs to travel. For example, performance may be excellent for employees working in the office next to the application’s endpoints, but poor for remote employees or those working overseas. Unicast also complicates scaling traffic loads — that single service location must ramp up resources when load increases, whereas anycast networks can share traffic across many data centers and geographies.

Figure 6 shows how using the Cloudflare network allows geographically disparate users to connect to their resources as fast as possible.

![Cloudflare’s global anycast network ensures that the closest data center is always selected](https://developers.cloudflare.com/_astro/lb-ref-arch-6.Bw_DeAYw_VJ60J.svg "Figure 6: Load balancers hosted on Cloudflare’s global anycast network")

Figure 6: Load balancers hosted on Cloudflare’s global anycast network

Figure 6, above, shows other Cloudflare services are also running in each of these data centers since Cloudflare runs every service in every data center so users have a consistent experience everywhere. For example, Cloudflare’s layer 7 load balancer will also be able to take advantage of other services such as DDoS protection, CDN/Cache, Bot Management, or WAF. All of these additional services can help protect your service from unnecessary traffic whether it be malicious requests (blocked by DDoS Protection, Bot Management, or WAF) or requests that can be served via cache rather than a request to endpoint. All of these services can be combined as needed to make a service or offering as protected, resilient, and performant as possible.

![Cloudflare Layer 7 features can be used together to further secure a service](https://developers.cloudflare.com/_astro/lb-ref-arch-7.BB-S-4sn_HuCjE.svg "Figure 7: Some of the processes a HTTP request passes through in the Cloudflare layer 7 stack")

Figure 7: Some of the processes a HTTP request passes through in the Cloudflare layer 7 stack

Cloudflare also has a [network optimization service ↗](https://blog.cloudflare.com/orpheus-saves-internet-requests-while-maintaining-speed/) that is constantly running at all data centers to ensure that Cloudflare provides the best path between Cloudflare data centers and also track all the available paths to endpoints. This allows Cloudflare to ensure that endpoints can always be reached and reroute traffic to alternate Cloudflare data centers, if necessary, to reach an endpoint. After the load balancer has made a decision on which endpoint to steer the traffic, the traffic is then forwarded to Cloudflare’s network optimization service to determine the best path to reach the destination. The path can be affected by a feature called Argo Smart Routing which, when enabled, uses timed TCP connections to find the Cloudflare data center with the fastest RTT to the endpoint. Figure 8 shows how Argo Smart Routing can help improve connection time to endpoints.

![Argo Smart Routing finds the fastest path between requester and endpoint](https://developers.cloudflare.com/_astro/lb-ref-arch-8.DxPypMMy_1yPSyw.svg "Figure 8: Argo Smart Routing reduces latency to endpoints")

Figure 8: Argo Smart Routing reduces latency to endpoints

Another way traffic flow can be affected is by the use of Cloudflare Tunnels. This document covers Cloudflare Tunnels in depth in the following section. Because Cloudflare Tunnels connect endpoints to specific Cloudflare data centers, traffic destined for those endpoints must traverse those data centers to reach the endpoint. Figure 9 shows how connections to private endpoints connected via Cloudflare Tunnel must pass through the data center where the tunnel terminates.

![Requests take different paths depending on whether the endpoint is public or connected over Cloudflare Tunnel](https://developers.cloudflare.com/_astro/lb-ref-arch-9.coisSp9H_1cdDiM.svg "Figure 9: Paths to endpoints differ when connecting endpoints via Cloudflare Tunnel")

Figure 9: Paths to endpoints differ when connecting endpoints via Cloudflare Tunnel

Usually, GTM and Private Network Load Balancers are either separate hardware or separate SaaS (GTM) and hardware Private Network Load Balancing components. Cloudflare’s GTM and Private Network Load Balancing capabilities are combined into a single SaaS offering which greatly simplifies configuration and management. There is no need to create a GTM load balancer and steer traffic to more local Private Network Load Balancers. All endpoints can be directly connected to Cloudflare and traffic is steered to the correct region, data center, and endpoint all from a single load balancer configuration. While the concepts of GTM and Private Network Load Balancing features will persist, their implementation in Cloudflare will be done in a way that keeps load balancer configurations as simple and straightforward as possible. Figure 10 illustrates how global traffic can be steered from any geographic region to a specific endpoint as needed.

![Combining GTM and Private Network Load Balancing functions into a single load balancer configuration](https://developers.cloudflare.com/_astro/lb-ref-arch-10.BICXl4Ld_Z2sioWk.svg "Figure 10: Cloudflare combines the function of GTM and Private Network Load Balancing")

Figure 10: Cloudflare combines the function of GTM and Private Network Load Balancing

### The structure of a Cloudflare Load Balancer

A Cloudflare Load Balancer, often referred to as a Virtual IP (VIP), is configured with an entrypoint. Typically, this entrypoint is a DNS record. The load balancer first applies a defined traffic steering algorithm to select an endpoint pool, which is a group of endpoints selected based on function, geographic area, or region. A load balancer configuration can have one or multiple endpoint pools, and each endpoint pool can have one or many endpoints. After selecting an endpoint pool, the load balancer applies an endpoint steering algorithm to the list of endpoints and selects an endpoint to steer the traffic towards. Figure 11 shows the basic steps from client request to endpoint within a Cloudflare Load Balancer.

![The steps within a Cloudflare Load Balancer](https://developers.cloudflare.com/_astro/lb-ref-arch-11.Bx2sEYiV_Z2ociBh.svg "Figure 11: The basic process flow through a Cloudflare Load Balancer")

Figure 11: The basic process flow through a Cloudflare Load Balancer

The definition of a Cloudflare Load Balancer is divided into three main components:

1. Health monitors: these components are responsible for observing the health of endpoints and categorizing them as healthy or critical (unhealthy).
2. Endpoint pools: this is where endpoints are defined and where health monitors and endpoint steering are applied.
3. Load balancers: in this component, lists of endpoint pools and traffic steering policies are applied.

The following sections detail the options available and considerations for configuring a Cloudflare Load Balancer, starting with steering, which is utilized in both endpoint pool and load balancer configurations.

### Steering types and methods

Steering is the core function of a load balancer and steering methods ultimately determine which endpoint is going to be selected when a load balancer is engaged. From the load balancer’s perspective, steering can be applied in two key areas.

The first is called ‘traffic steering’, and it is responsible for determining which endpoint pool will handle incoming requests, typically based on proximity or geographic region of the requester. The concept of traffic steering closely aligns with the idea of global traffic management.

The second area where steering is applied is after a region, data center, or endpoint pool has been selected. At this point, the load balancer needs to select the single endpoint responsible for handling the request or connection, referred to as ‘endpoint steering’. Steering at both of these levels is done by applying steering methods tailored to the specific needs of the customer deploying the load balancer. There are several different algorithms to choose from, but not all algorithms are applicable to both steering types.

Below is an in-depth review of all the steering methods Cloudflare offers. At the end of this section, there is a quick reference table which can be helpful in understanding which algorithms are applicable to which use cases.

#### Traffic steering

Traffic steering selects the group of endpoints, also called an endpoint pool. The most common use of traffic steering is to select the endpoint pool based on the least latent response times, geographic region, or physical location. Traffic steering is closely aligned to global traffic management and serves as the initial step in directing traffic to an endpoint.

#### Endpoint steering

Endpoint steering is responsible for selecting which endpoint will receive the request or connection. Endpoint steering can randomly select an endpoint, a previously selected endpoint (if session affinity is enabled), or it can be used to select the least utilized, fastest responding, endpoint for a request or connection. Endpoint steering is closely related to Private Network Load Balancing, as it is responsible for selecting the final destination of a request or connection.

#### Weighted steering

Weighted steering takes into account the differences in endpoint pools and endpoints that will be responsible for handling requests from a load balancer. Endpoint weight, which is a required field for every endpoint, is only used when specific steering methods are chosen. Similarly, endpoint pool weight is only needed when specific steering methods are selected. Please see the [steering options overview](#steering-options-overview) section for a quick reference for when weights are applied.

Weight influences the randomness of endpoint pool or endpoint selection for a single request or connection within a load balancer. Weight does not consider historical data or current connection information, which means that weight may have variations in distribution over shorter timeframes. However, over longer periods of time and with significant traffic, the distribution will more closely resemble the desired weights applied in configuration. It’s important to note that session affinity will also override weight settings after the initial connection, as session affinity is intended to direct subsequent requests to the same endpoint pool or endpoint. Figure 12 shows a weight example for two endpoint pools with equal capacity and probability of being selected.

![A pair of endpoint pools with equal probability of being selected](https://developers.cloudflare.com/_astro/lb-ref-arch-12.Buje8NxO_Z1t79ta.svg "Figure 12: A pair of endpoint pools with equal capacity")

Figure 12: A pair of endpoint pools with equal capacity

Specific algorithms, such as Least Outstanding Request Steering, take into account the number of open requests and connections. Weight is used to determine which endpoints or endpoint pools can handle a greater number of open requests or connections. Essentially, weight defines the capacity of endpoints or endpoint pools, regardless of the selected steering method.

Weight is defined as any number between 0.00 and 1.00\. It’s important to note that the total weight of the endpoint pools or the endpoints within an endpoint pool do not need to equal 1\. Instead, the weights will be added together, and then an individual weight value is divided by that sum to get the probability of that endpoint being selected.

Weight to percentage equation: (endpoint weight) ÷ (sum of all weights in the pool) = (% of traffic to endpoint)

Below are some examples with diagrams to help in understanding how weight is used for distributing traffic. In these examples, it is assumed that the goal is to evenly distribute traffic across all endpoints with the same capacity or compute resources. [Random](#random-steering) traffic steering will be used to demonstrate traffic distribution across three endpoint pools.

Example 1:

* There are three endpoint pools defined, all with a weight of 1
* Each endpoint pool has a 33% probability of being selected

Example math for weight of 1: (1) ÷ (1 + 1 + 1) = (.3333) (or 33.33%)

![A set of three endpoint pools all with equal probability](https://developers.cloudflare.com/_astro/lb-ref-arch-13.BIZS6w9__ygYRV.svg "Figure 13: Three endpoint pools with equal weight")

Figure 13: Three endpoint pools with equal weight

In this example, it was simple to apply 1 to all the weight values for each of the endpoint pools. However, it should be noted that any number between 0.01 and 1.00 could have been used as long as the same number was used across all three endpoint pools. For instance, setting all three pools to .1 or even .7 would have resulted in an equal probability that each pool would be selected to receive traffic.

Since the sum of the weights is used to calculate the probability, organizations can use any number of values to make these inputs easier to understand. In the following examples, since each endpoint has the same capacity, a value of .1 weight is assigned to each endpoint, and the sum of these values is used as the weight for the endpoint pool.

Example 2

* There are three endpoint pools defined
* Each endpoint pool has a different number of endpoints, but all endpoints have equal capacity
* To evenly distribute load across endpoints, each endpoint pool needs a different probability

![Three endpoint pools with different numbers of endpoints](https://developers.cloudflare.com/_astro/lb-ref-arch-14.ChU-xE19_zNzhL.svg "Figure 14: Illustrates how to use weight to balance load across endpoint pools with different capacity")

Figure 14: Illustrates how to use weight to balance load across endpoint pools with different capacity

Example math for weight of .4 : (.4) ÷ (.4 + .5 + .6) = (.2667) (or 26.67%)

Example math for weight of .5 : (.5) ÷ (.4 + .5 + .6) = (.3333) (or 33.33%)

Example math for weight of .6 : (.6) ÷ (.4 + .5 + .6) = (.4000) (or 40.00%)

It is possible that endpoints do not all have the same capacity. In the following example, one of the endpoint pool’s endpoints has twice the capacity of the endpoints in the other two endpoint pools.

Example 3

* There are three endpoint pools defined
* Endpoint pool 1 has endpoints that have double the capacity compared to those in endpoint pool 2 and endpoint pool 3
* The goal is to place double the amount of traffic to endpoint pool 1 per endpoint
* Endpoint pool 1 has 4 endpoints but with double capacity, the weight of each endpoint will be valued at .2 for a total of .8 for the endpoint pool

![Three endpoint pools with different numbers of endpoints and endpoints of different capacity](https://developers.cloudflare.com/_astro/lb-ref-arch-15.CJwKtgsv_2tvur8.svg "Figure 15: Using weight to balance load across endpoint pools with different capacities and endpoints")

Figure 15: Using weight to balance load across endpoint pools with different capacities and endpoints

Example math for weight of .8 : (.4) ÷ (.8 + .5 + .6) = (.4211) (or 42.11%)

Example math for weight of .5 : (.5) ÷ (.8 + .5 + .6) = (.2632) (or 26.32%)

Example math for weight of .6 : (.6) ÷ (.8 + .5 + .6) = (.3157) (or 31.57%)

In this final example, since the four endpoints in endpoint pool 1 are double the capacity of other endpoints, the calculation treats endpoint pool 1 as if it essentially has 8 endpoints instead of 4\. Therefore, the weight value of .8 instead of .4 as shown in example 2.

These are just three simple examples illustrating how weight can be used to distribute load across endpoint pools or endpoints. The same calculations are used for weights applied to endpoints within an endpoint pool as well. However, the impact of using weights within different steering methods is similar, although with slightly modified calculations, as covered in the sections below.

Weights are most useful when one endpoint pool might have more resources than another endpoint pool or when endpoints within an endpoint pool do not have equal capacity. Weight helps to ensure that all resources are used equally given their capabilities.

#### Steering methods

##### Off - failover

Off - failover is the most basic of traffic steering policies. It uses the order of the endpoint pools as a priority list for selecting which pool to direct traffic towards. If the first pool in the list is healthy and able to receive traffic, that is the pool that will be selected. Since off - failover isn’t available for endpoint steering, another steering method will be used to select an endpoint. Off - failover is commonly used in active/passive failover scenarios where a primary data center or group of endpoints is used to handle traffic, and only under failure conditions, is traffic steered towards a backup endpoint pool.

##### Random steering

Random steering is available for both traffic steering and endpoint steering. Random spreads traffic across resources based on the weight defined at both the load balancer configuration and within the endpoint pool. The weight values set at the load balancer for each endpoint pool can differ from the weight value set per endpoint within that endpoint pool. For example, within a load balancer configuration, 70% of traffic can be sent to one of two endpoint pools, then within that endpoint pool, the traffic can be evenly distributed across four endpoints. The previous section, [weighted steering](#weighted-steering), provides a detailed explanation of how weight is used and the calculations that determine the selection of an endpoint pool or endpoint.

##### Hash steering

Hash steering is an endpoint steering algorithm that uses endpoint weight and the request’s source IP address to select an endpoint. The result is that every request from the same IP address will always steer to the same endpoint. It’s important to note that altering the order of endpoints or adding or removing endpoints from the endpoint pool could result in different outcomes when using the hash algorithm.

##### Geo steering

Geo steering is a traffic steering algorithm available to enterprise plan customers that is used to tie endpoint pools to specific countries or geographic regions. This option can be useful for improving performance by steering traffic to endpoints closer to users. It also aids in complying with laws and regulations by steering requests from users in specific regions to resources within the same region or to resources designed to meet specific regulatory requirements.

##### Dynamic steering

Dynamic steering is a traffic steering algorithm available to enterprise plan customers that creates round trip time (RTT) profiles. RTT values are collected each time a health probe request is made and based on the response from the endpoint to the monitor request. When a request is made, Cloudflare inspects the RTT data and sorts pools by their RTT values. If there is no existing RTT data for your pool in a region or colocation center, Cloudflare directs traffic to the pools in failover order. When enabling dynamic steering the first time for an endpoint pool, allow 10 minutes for the change to take effect as Cloudflare builds an RTT profile for that pool. Dynamic steering doesn’t use geographic boundaries in its decision making process and solely focuses on selecting the lowest RTT endpoint pool.

##### Proximity steering

Proximity steering is a traffic steering algorithm available to enterprise plan customers that steers traffic to the closest physical data center based on where the request endpointated.

Cloudflare determines the requester’s physical location using the following methods, in this order:

1. [EDNS Client Subnet ↗](https://developers.google.com/speed/public-dns/docs/ecs) information, if provided in the DNS request
2. Geolocation information of the resolver used to reach Cloudflare
3. GPS location of the Cloudflare data center handling the request

Proximity steering requires providing GPS coordinates for all endpoint pools, allowing Cloudflare to calculate the closest endpoint pool based on the requesting IP, DNS resolver, or Cloudflare data center.

##### Least outstanding requests steering (LORS)

Least outstanding request steering (LORS) is available to enterprise plan customers and can be used for both traffic and endpoint steering.

LORS uses the number of unanswered HTTP requests to influence steering and is only functional when used with Cloudflare Layer 7 proxied Cloudflare Load Balancers. If LORS is assigned to any other type of load balancer, its behavior will be equivalent to random steering. LORS uses the counts of open requests, along with weight, to create a new transformed weight that is used for the steering decision.

Equation for LORS transformed weight:

* weight / (count + 1) = transformedWeight

Reminder for random weight calculation:

* weight / (total weight) = probability of being selected

Here’s an example of LORS:

* Pool A has a weight of 0.4
* Pool B has a weight of 0.6
* Pool A has 3 open requests
* Pool B has 0 open requests
* Relevant equation  
   * weight / (count + 1) = transformedWeight
* Pool A's transformed weight: 0.4 / (3 + 1) = 0.1
* Pool B's transformed weight: 0.6 / (0 + 1) = 0.6
* Relevant equation  
   * weight / (total weight) = probability of being selected
* Pool A’s probability of being steered toward: 0.1 / (0.1+0.6) = .1429 (14.29%)
* Pool B’s probability of being steered toward: 0.6 / (0.1+0.6) = .8571 (85.71%)

In this example, the next connection has a 14.29% probability of being steered to Pool A and a 85.71% probability of being steered to Pool B. While it’s likely that traffic will be steered towards Pool B, it is still possible for it to be steered to Pool A. In situations with lighter load conditions, there will be more variation in the steering results, which may not precisely match the configured weights. However, as the load increases, the actual steering results will closely match the configured weights.

When non-L7 proxied load balancers are used with LORS, the open request count information is not available. As a result, the denominator will always be 1\. Since dividing any number by 1 doesn’t change the numerator, and in this case, the numerator is the weight, steering decisions will be made solely on weight. This results in the random method described above.

LORS is best used if endpoint pools or endpoints are easily overwhelmed by spikes in concurrent requests. It is well-suited for applications that value endpoint health over factors like latency, geographic alignment, or other metrics. This is especially useful when some or all requests put a heavy load on an endpoint and take a significant amount of time to generate a response.

#### Steering options overview

| Steering Method            | Traffic Steering | Endpoint Steering | Weight-based | Enterprise-only |
| -------------------------- | ---------------- | ----------------- | ------------ | --------------- |
| Off - Failover             | X                |                   |              |                 |
| Random                     | X                | X                 | X            |                 |
| Hash                       | X                | X                 | X            |                 |
| Geo                        | X                | X                 |              |                 |
| Dynamic                    | X                | X                 |              |                 |
| Proximity                  | X                | X                 |              |                 |
| Least Outstanding Requests | X                | X                 | X            | X               |

All traffic steering methods marked above as Enterprise-only can also be obtained as a self-service add-on as well. All endpoint steering methods marked as Enterprise-Only require an enterprise plan with Cloudflare.

### Health monitors

A health monitor determines the health of endpoints once they are configured inside an endpoint pool. Health monitors generate probes, which are connection attempts to endpoints. Health monitors use the responses to the probes to record endpoint health. Health monitors serve as templates that include service type, path, and port, and advanced features such as interval, timeout, and protocol specific settings for evaluating endpoint health. The health monitor template is then applied to the endpoint pool, which contains endpoints hosting similar services. Once a health monitor is attached to the endpoint pool, the endpoint address is used as the destination for the health monitor probe. A single health monitor can be used across many endpoint pools, and health monitors are account-level objects, allowing them to be leveraged by multiple zones within the same Cloudflare account.

By default, health monitor probes are sent directly to the endpoint address, bypassing the entire layer 7 stack. This means that actual traffic to the endpoint through the load balancer will receive different treatment than the health monitor probe. Depending on the configuration, this could result in a health monitor reporting an endpoint as healthy, even if actual connections or requests are failing.

The Simulate Zone feature ensures that health monitor probes follow the same path as layer 7 HTTP/HTTPS requests for the given zone, passing through the same Cloudflare software-defined routing for egress to origin. This ensures health monitors take the same path through the Cloudflare network and other layer 7 processes to reach the origin endpoint.

The Simulate Zone feature is required for health monitors when certain features are enabled at the zone level, such as [Authenticated Origin Pulls](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/) or [Bring your own CA](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/), where probes would fail if they weren’t being provided with the proper mTLS certificate or authority for authentication with the origin server. Simulate Zone also ensures health monitor probes use the same path provided by [Argo Smart Routing](https://developers.cloudflare.com/argo-smart-routing/) and the same [Dedicated CDN Egress IPs](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/) when organizations leverage [Smart Shield Advanced](https://developers.cloudflare.com/smart-shield/get-started/#packages-and-availability) to restrict the edge IP addresses that Cloudflare uses to reach their endpoints.

![HTTPS health monitor to monitor the status of an endpoint](https://developers.cloudflare.com/_astro/lb-ref-arch-16.BYSozQzy_Z1LA0T2.webp "Figure 16: HTTPS health monitor configuration")

Figure 16: HTTPS health monitor configuration

Health monitor Probes can be configured as the following types:

* HTTP
* HTTPS
* TCP
* UDP ICMP
* ICMP Ping
* SMTP
* LDAP

Once a health monitor is defined, it can be assigned to an endpoint and the probes will be sent to the endpoint at the interval defined. There are two additional settings to note in regards to the health monitor configuration within the endpoint pool. The first is the Health Threshold, which is used to determine how many endpoints within the pool need to be healthy in order to consider the endpoint pool to be healthy or degraded.

* Endpoint pool in healthy state  
   * Contains only healthy endpoints
* Endpoint pool in degraded state  
   * Contains at least one critical endpoint but remains at or above the health threshold setting
* Endpoint pool in critical state  
   * Contains healthy endpoints below the health threshold  
   * Not capable of handling traffic; removed from all steering decisions.

![Comparison of three endpoint pools with different numbers of healthy endpoints](https://developers.cloudflare.com/_astro/lb-ref-arch-17.BM3mVtFf_Z1UUgUA.svg "Figure 17: When endpoints pool are considered healthy, degraded, or critical")

Figure 17: When endpoints pool are considered healthy, degraded, or critical

The second setting after defining the health monitor in the endpoint pool is to define which regions the health monitor probes should source from inside the Cloudflare global network. The available selections are listed below:

* All Regions (Default)
* All Data Centers (Enterprise Only)
* Western North America
* Eastern North America
* Western Europe
* Eastern Europe
* Northern South America
* Southern South America
* Oceania
* Middle East
* Northern Africa
* Southern Africa
* Southern Asia
* Southeast Asia
* Northeast Asia

![Endpoint pool settings to further customize the health monitors](https://developers.cloudflare.com/_astro/lb-ref-arch-18.BeeIf21t_16mIgt.webp "Figure 18: Health Threshold and region selection for an endpoint pool configuration")

Figure 18: Health Threshold and region selection for an endpoint pool configuration

With the exception of “All Regions” and “All Data Centers”, health monitor probes will only originate from data centers in the selected region or regions. For locally relevant services, it may not matter whether or not a data center on the other side of the world can reach the endpoints. Therefore, limiting checks to a specific region or a set of regions may make sense. The selection of “All Regions” or “All Data Centers” is intended to be used for globally available services where reaching a set of endpoints could be crucial to the function of the application.

### Endpoints and endpoint pools

Endpoints are the actual servers that handle connections and requests after a load balancer has applied all its policies. Endpoints can be physical servers, virtual machines, or serverless applications. As long as they can handle a request or connection from a user or client, they can be considered an endpoint. There are several different methods of defining and connecting endpoints to Cloudflare and the next section details those methods.

#### Connecting endpoints to Cloudflare

Cloudflare endpoints can be defined in two ways, by IP address or by hostname. IP addresses are the most straightforward and basic of connection methods, hostnames offer a few options to consider. A hostname can be defined in Cloudflare DNS and it can be proxied or DNS-only (unproxied). Another option, of course, is that the hostname is not in a domain which Cloudflare is an authoritative DNS server for which means Cloudflare will rely on outside DNS servers to resolve that hostname to an IP address. Cloudflare Tunnel can also be used and offers two different options as well. These methods are discussed below in this section.

##### Cloudflare proxied, DNS, IP, and non-Cloudflare endpoints

As mentioned in the “HTTP(S) Load Balancing” section above, load balancing is the very last process run before a request is sent to an endpoint. In the case of however, even if an endpoint is proxied via Cloudflare’s edge, after the load balancer, the request is forwarded directly to the endpoint without passing through the layer 7 stack again. This doesn’t mean the endpoint is unprotected or uncached, however. As long as the load balancer itself is proxied then all those protections are provided to the load balancer rather than the endpoints. Any direct communication with the endpoint can still be proxied and treated with Cloudflare’s layer 7 stack, but communication with an endpoint places all the processing in front of the load balancer, not the endpoint. Figure 19 illustrates the difference of where the Cloudflare layer 7 stack is placed in relation to the endpoint(s).

![Load balancing is the last process before dispatching to the endpoint](https://developers.cloudflare.com/_astro/lb-ref-arch-19.CKZfc_hA_Z18MGx.svg "Figure 19: Differences in the Layer 7 paths between load balancer and endpoint")

Figure 19: Differences in the Layer 7 paths between load balancer and endpoint

There are very few differences from a load balancer perspective when it comes to what type of endpoint is defined as part of an endpoint pool. Once the traffic and endpoint steering policies and the load balancer rules are applied, the Cloudflare Load Balancing service instructs the L7 stack where to forward the incoming request or connection. This request is sent directly to the endpoint. Depending on the type of connection to the endpoint, there may be a different path. Features like Argo Smart Routing or tunnel-connected endpoints that are terminated at different Cloudflare data centers will route traffic differently rather than sending the request out of the Cloudflare edge, over the internet, directly to the endpoint. Regardless of the path, however, load balancing is the last process in the stack and this means that traffic doesn’t receive any additional treatment. So while the connection to endpoint can change the path from Cloudflare to the endpoint, the treatment or processing doesn’t change once an endpoint is selected.

##### Cloudflare Tunnel

Cloudflare Tunnel is an outbound connection that enables organizations to simplify their firewall configurations, reduce complexity, enhance security, and more easily join their assets to the Cloudflare network. The executable that creates these tunnels is called cloudflared and may be referenced in this document and diagrams that follow.

Cloudflare Tunnel (cloudflared) can be installed directly on the endpoint or any server with IP connectivity to the endpoint. And because the connection to Cloudflare is initiated from where Cloudflare Tunnel was installed to Cloudflare, the only access needed is outbound access to Cloudflare. A single Cloudflare Tunnel can transport traffic to one or many different endpoints in one of two different ways, one which results in the endpoint being publicly accessible and one which keeps the endpoint completely only accessible privately.

Cloudflare Tunnel can be installed on the endpoint itself or on any server with layer 3 (IP) connectivity to the endpoint or endpoints that need to be connected to Cloudflare. The decision to separate cloudflared could be made for many different reasons including but not limited to isolating the endpoint(s) and ensuring their performance, having separate teams that manage network level connectivity and endpoints, or separation for architectural simplicity where servers have segregated roles or responsibilities.

![A single cloudflared instance tunnels traffic for multiple endpoints](https://developers.cloudflare.com/_astro/lb-ref-arch-20.BehqGz1M_2po7El.svg "Figure 20: A shared cloudflared deployed on a separate server tunnels traffic for multiple endpoints")

Figure 20: A shared cloudflared deployed on a separate server tunnels traffic for multiple endpoints

A single cloudflared instance will create 4 different tunnels, two tunnels in two different Cloudflare data centers. This model ensures high availability and mitigates the risk of individual connection failures. This means in event a single connection, server, or data center goes offline, the endpoints will remain available. Cloudflare Tunnel also allows organizations to deploy additional instances of cloudflared, for availability and failover scenarios. These unique instances are called replicas. Each replica establishes four new connections which serve as additional points of ingress to the endpoint(s). Each of the replicas will point to the same tunnel. This ensures that your network remains up in the event a single host running cloudflared goes down. By design, replicas do not offer any level of traffic steering (random, hash, or round-robin).

###### Public hostname

The public endpoint method allows organizations to define a tunnel that points to a specific service or port running on an endpoint. The tunnel can terminate on the endpoint or on any server with IP connectivity to the endpoint. Using this public hostname method requires that each service that will be accessed over the tunnel is defined in the tunnel configuration. When configured, a unique tunnel ID, such as d74b3a46-f3a3-4596-9049-da7e72c876f5, will be created for the IP and port or service for which the tunnel is connecting traffic. This tunnel ID is then created into a unique public hostname in the Cloudflare-owned domain of cfargotunnel.com which results in a DNS A record being created that points directly to that service, I.E. d74b3a46-f3a3-4596-9049-da7e72c876f5.cfargotunnel.com. While this hostname is public it can only be accessed or utilized by traffic that is sent through the account that owns the Cloudflare Tunnel configuration. No other accounts would be able to access or send traffic directly to this DNS address. A DNS CNAME record created outside of the account that owns the cfargotunnel.com hostname will not be able to send traffic through that specificCloudflare Tunnel.

When configured via the Dashboard, Cloudflare automatically creates a CNAME record in the DNS zone that refers to the cfargotunnel.com hostname. For example, a CNAME record of myTunnelService.example.com could be created to point the A record of d74b3a46-f3a3-4596-9049-da7e72c876f5.cfargotunnel.com. The main benefit being the ease of use and administration as the CNAME record is much more suggestive about its purpose and belongs to the customer DNS zone.

Another option is to create these tunnels and services on the host running cloudflared. This is called a [locally-managed tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/local-management/). When working with locally-managed tunnels, the CNAME entry is not created automatically however, so the organization would have to configure this manually, after the tunnel and service is defined.

From a load balancer perspective, it's very important to understand how these tunnels can be used as an endpoint. An endpoint can only be defined by using the cfargotunnel.com hostname. Using a public CNAME record that points to the cfargotunnel.com address will not work properly and is not supported. This is especially important for endpoint services that don’t operate on ports 80 or 443\. Cloudflare Load Balancers default to these two ports to access the services running on the endpoints. If an organization has services running on other ports, they will need to configure a Cloudflare Tunnel with a [catch-all rule](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/local-management/configuration-file/#how-traffic-is-matched) to reach that port. This configuration allows a Cloudflare Load Balancer to reach the service via port 443 while having Cloudflare tunnel proxy the connection to the desired port on the endpoint.

###### Private IP

The second method is for private subnets. This method allows organizations to define private IP addresses and a subnet mask which will be used to create a private virtual network within the Cloudflare global network. The private subnet method does not allow the definition of a port and as such, once a subnet and mask are defined, the entire subnet can be reached over that tunnel but only to users within the organization that are allowed access via defined Zero Trust policies.

This subnet then gets added to the virtual network inside of Cloudflare where the customer can control how users can access it and which users can access it. This subnet can be defined for any desired subnetting or routing, including using a 32-bit mask (single IP address, i.e., 10.0.0.1/32). The allowed subnet does not need to exist on the host that is running the cloudflared process either. All that is required is layer 3 or IP connectivity between the host running cloudflared and the subnet that is going to be reachable over Cloudflare Tunnel.

#### Endpoint pool details

Within the endpoint pool, there are several configuration options. This section details what these configuration options are and how they alter the behavior of a Cloudflare Load Balancer.

##### Endpoint steering

The first configuration, besides defining a name and description of the endpoint pool, is to determine the endpoint steering method. Endpoint steering is responsible for ultimately selecting the endpoint or endpoint that will receive the request or connection attempt (please refer to the [Steering methods](#steering-methods) section for a detailed description of each method).

##### Endpoints

Individual endpoints are defined within endpoint pools, and the endpoint pool allows for one or more endpoints to be defined per pool.

* The _endpoint name_ is primarily used for reference, reporting, and analytics; it does not affect the function of the load balancer or endpoint pool.
* The _endpoint address_, however, defines a resource that the load balancer can use to handle a request or connection.  
   * Endpoints within an endpoint pool must be accessible over port 80 or 443\. If the endpoint is not listening on port 80 or 443, then either a proxy service or network port forwarding device needs to be placed in front of the endpoint to map port 80 or 443 to the port that the service is actually listening on.  
   * Another method for mapping ports of endpoints to 80 or 443 is to connect to the endpoint service using [Cloudflare Tunnel](#cloudflare-tunnel), and then use the hostname created through that process as the endpoint address. This will automatically map the intended endpoint port to port 443.

_Endpoint address_ can be defined in one of the following ways:

* Publicly routable IP address
* Cloudflare-proxied publicly reachable hostname
* Publicly reachable non-Cloudflare hostname
* Private, non-publicly routable IP address with the selection of a virtual network

##### Virtual networks

Using public IPs and hostnames of any type require no additional configuration. In those scenarios, the virtual network should be set to the default value of “_none_”. The “_none_” setting signals that these resources will be accessible on the public Internet, routed via Cloudflare’s global edge network.

The use of the _virtual network_ option is reserved for private IP resources. This setting maps to IP subnets that are hosted behind [Cloudflare Tunnel configurations](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/). A virtual network should be selected that has a route to the IP address of the endpoint. To navigate to this setting in the Cloudflare Dashboard, select _Networks - Routes_ from the Zero Trust page.

##### Endpoint weight

_Endpoint weight_ is only used for the random, hash, and least outstanding request steering methods; it must always be defined as part of the endpoint definition. (Please refer to the [Weighted Steering](#weighted-steering) section for more information on how weights are used for endpoint selection.)

##### Host header modification

Endpoint pools allow for the host header to be modified before dispatching a request to an endpoint. This configuration only applies to the HTTP(S) layer 7 load balancer (it will be ignored when used with layer 4 load balancers, including private IP and Spectrum).

Within a layer 7 load balancer where requests are HTTP(S)-based, the Host header tells the endpoint which website is being requested, as a single endpoint may host several different web domains. When an endpoint is specifically configured to host a web domain, it may either not respond or send a failure response to a request for a resource, if it does not believe it is hosting the resource requested in the Host header (i.e., if there are mismatched Host headers).

For example:

* Say a user tries to reach `www.example.com`. The load balancer will be configured with the hostname of `www.example.com`to receive all the requests.
* Since the endpoints can’t have the same public hostname in DNS, its hostname is `endpoint1.example.com`.
* When the user makes a request to `www.example.com,` the Host header will be set to` www.example.com,` as well. The endpoint will need to be configured to respond to Host headers of `www.example.com`.
* In some cases (such as with certain cloud or SaaS applications), however, endpoints aren’t configurable in that manner, so the endpoint may receive a request with an unknown Host header and fail to respond appropriately.
* In this example, in the endpoint configuration, setting the Host header for the endpoint to the endpoint address of `endpoint1.example.com` will replace the Host header of `www.example.com` with `endpoint1.example.com`, and will allow the endpoint to properly respond to this request.

Figure 21 highlights the potential problem of mismatched Host headers:

![Mismatched Host headers may result in the endpoint rejecting the request](https://developers.cloudflare.com/_astro/lb-ref-arch-21.Bs0qP_r-_2hJASL.svg "Figure 21: How the load balancer can rewrite the Host header to match the endpoint")

Figure 21: How the load balancer can rewrite the Host header to match the endpoint

Also, at the endpoint pool, GPS coordinates for the pool (which are used with proximity traffic steering) can be defined. If proximity steering is not being used, then these coordinates are not required (please refer to the [Proximity Steering](#proximity-steering)).

##### Load shedding

[Load shedding](https://developers.cloudflare.com/load-balancing/additional-options/load-shedding/) — a real-time response available to administrators to protect against endpoints in a pool that are [becoming unhealthy ](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/) — is also configured on the endpoint pool.

The load shedding setting is not intended to be enabled unless an administrator is trying to actively protect an endpoint pool from becoming unhealthy. It is activated, for example, when an endpoint that is still responding to requests is experiencing increased CPU or memory usage, increased response times, or occasionally failing to respond at all.

When an endpoint pool’s health begins to degrade, load shedding can help direct some of the existing loads from one endpoint pool to another.

Depending on the health of the endpoint pool, it may be enough to simply shed or redirect new requests and connections away from the endpoint pool. This policy applies to traffic, which is not subject to any session affinity rules since these are new connections that haven’t had an endpoint pool or endpoint selected yet (and, therefore, will not potentially affect the end user experience).

Should an endpoint pool approach critical failure due to load, the next option is to shed additional session affinity traffic. This will start to redirect requests and connections that are bound to endpoint pools through session affinity as well. However, please note that because this process can ultimately change the user’s endpoint, it could impact the end user’s experience. Ultimately, the impact is determined by the application that is being load balanced, and how much connection context is shared between endpoints.

##### Health monitors

Health monitors are attached to endpoints at the endpoint pool as well as health threshold and the health check region selection. Details of these options can be found in the [health monitor](#health-monitors) section.

### Load balancers

Load balancing within Cloudflare combines both GTM and Private Network Load Balancing into a single load balancer configuration. While certain features or terms may align more with GTM or Private Network Load Balancing, for Cloudflare customers, both are combined into a single, easy-to-manage instance.

Depending on their specific use case, organizations can leverage different types of Cloudflare Load Balancers. The following section highlights the main differences between the deployment models, and articulates when each type of load balancer should be implemented.

Figure 22 highlights all the possible combinations of load balancers and endpoints supported by Cloudflare:

![All the possible combinations of load balancer and endpoint types](https://developers.cloudflare.com/_astro/lb-ref-arch-22-ALT.DPr9OdxY_1kYKMO.svg "Figure 22: The combinations of public and private load balancers and endpoints and how they connect")

Figure 22: The combinations of public and private load balancers and endpoints and how they connect

#### Deployment models

Cloudflare offers three load balancing deployment models, each of which support different use cases, functionality, and privacy requirements.

* [Layer 7 HTTP(S) load balancing](#layer-7-https-load-balancing)
* [DNS-only load balancing](#dns-only-load-balancing)
* [Spectrum load balancing](#spectrum-load-balancing)

Except for the DNS-only load balancing option described in more detail below, all of the deployment models anchor traffic through the load balancer. This means the user or client creating the request or connection is never aware of the endpoints that are being used to service the request or connection. Endpoint information can certainly be exposed — if desired — through the use of headers, but this is not default behavior for any of these anchored deployment models.

The following explores the four main deployment models (and their differences) in more detail.

##### Layer 7 HTTP(S) load balancing

First, the most common model is the **HTTP(S)-based layer 7 proxied load balancer**. These load balancers exist on Cloudflare’s edge and are publicly reachable. Amongst other features, this model supports [WebSockets](https://developers.cloudflare.com/network/websockets/), which are open connections between the client and endpoint allowing for data to be passed back and forth between the two.

Because this same layer 7 security stack also provides WAF, DDoS protection, Bot Management, Zero Trust, and other services, accessing these public load balancers can be restricted to authenticated and authorized users as needed. (Please refer to [Securing Load Balancers](#protecting-and-securing-load-balancers) for more information.)

In this layer 7 stack, load balancing can further improve the performance, reliability, and reachability of an organization’s public-facing web assets. The endpoints for these load balancers may be deployed in public cloud, private cloud, on-premises, or any combination thereof within the same load balancer. (Please refer to [Connecting endpoints to Cloudflare](#connecting-endpoints-to-cloudflare) for more details about how to connect endpoints to Cloudflare’s edge network).

![Layer 7 load balancing request flow to two different types of endpoints](https://developers.cloudflare.com/_astro/lb-ref-arch-23-ALT.DRZo2XIF_1kYKMO.svg "Figure 23: How Cloudflare’s Layer 7 load balancers can steer traffic to both public and private endpoints")

Figure 23: How Cloudflare’s Layer 7 load balancers can steer traffic to both public and private endpoints

As illustrated in Figure 23 above, the load balancing component of the layer 7 stack is the last process run on a request as it moves towards the endpoint. This can have a large positive impact on increasing performance and reducing load on endpoints.

For example, caching can prevent requests from ever reaching the endpoint and can be responded to without ever having to engage the load balancers. Also, WAF, DDoS protection, and Bot Management can eliminate attack traffic altogether — leaving more capacity for legitimate traffic.

Once a request reaches the load balancer process, the request is always sent directly to the endpoint that was selected. This means that even if the endpoint is proxied through Cloudflare, the request will be sent directly to the endpoint and receives no further processing.

For customized treatment after the load balancer selects an endpoint, the load balancer’s Custom Rules are applied. (This is covered in detail in the [Load balancers](#load-balancers) section below).

**Important notes about Layer 7 HTTP(S) load balancers:**

* Layer 7 HTTP(S) load balancers support both public and private endpoints
* Layer 7 HTTP(S) load balancers will only support HTTP(S) and WebSocket traffic
* Zero trust policies can be applied to Layer 7 HTTP(S) load balancers

##### DNS-only load balancing

Cloudflare’s DNS-only load balancer is an unproxied load balancer. This means that only the initial DNS request for the resource — not the actual traffic — passes through the Cloudflare edge. Therefore, instead of a DNS request resolving to a Cloudflare IP and then moving through the layer 7 stack as seen earlier in Figure 7, Cloudflare receives a DNS request for a DNS-only load balancer, applies all the appropriate load balancing policies, then returns an IP address to the requesting client to reach out directly.

Because all the traffic between the client and the endpoint will travel directly between the two and not through Cloudflare’s layer 7 stack, any type of IP traffic can be supported by a DNS-only load balancer.

![The orange cloud icon represents a proxied Layer 7 Cloudflare Load Balancer](https://developers.cloudflare.com/_astro/lb-ref-arch-24.Bw_izDOL_114CG5.webp "Figure 24: A proxied load balancer configuration")

Figure 24: A proxied load balancer configuration

![The gray cloud icon represents an unproxied \(DNS-only\) load balancer](https://developers.cloudflare.com/_astro/lb-ref-arch-25.Dz4ThM-k_2oDFUF.webp "Figure 25: An unproxied (DNS-only) load balancer configuration")

Figure 25: An unproxied (DNS-only) load balancer configuration

Even though Cloudflare does not proxy these types of load balancer connections, the health monitor service is still monitoring the health on all the endpoints in the pool. Based on the health or availability of an endpoint, a Cloudflare DNS-only load balancer will either add or remove an applicable endpoint to a DNS response to ensure that traffic is being steered to healthy endpoints.

![DNS-only load balancers only use Cloudflare to respond to a DNS request](https://developers.cloudflare.com/_astro/lb-ref-arch-26.BB1TuXz__Zaj07b.svg "Figure 26: How Cloudflare’s DNS-only load balancer functions")

Figure 26: How Cloudflare’s DNS-only load balancer functions

After a DNS-only load balancer has selected an endpoint pool via traffic steering, one or many IP addresses may be returned in the DNS response.

The decision to send one or many IP addresses within the DNS response is based on the weight assigned to the endpoints within the selected endpoint pool:

* If all the weights are equal across all endpoints, all IP addresses of all the endpoints will be returned in DNS response.
* If at least one endpoint is specified with a unique weight within the endpoint pool, then only a single IP address will be returned in the DNS response — regardless of the endpoint steering method selected on the endpoint pool.

This gives organizations the flexibility to allow applications to be aware of all the endpoints and perform local failover, or to allow Cloudflare to provide a single IP for an application to utilize.

Figure 27 shows how the defined weight within an endpoint pool can affect how a DNS-only load balancer responds.

![DNS-only load balancers can respond to DNS requests with one or many IP addresses](https://developers.cloudflare.com/_astro/lb-ref-arch-27.CJr7dL0T_Zrfoln.svg "Figure 27: How weight affects the DNS response from a DNS-only load balancer")

Figure 27: How weight affects the DNS response from a DNS-only load balancer

Please note that DNS-only load balancers have a few limitations compared to proxied load balancers:

* The load balancer no longer hides the endpoint’s IP address from the client as it is sent back to the client directly.
* They do not have the built-in layer 7 stack services mentioned in the previous model; i.e., DNS-only load balancers do not include caching, WAF, DDoS protection, or Zero Trust support.
* Session affinity is limited to `ip_cookie`, which will select an endpoint deterministically and then map that endpoint to the client IP address for all subsequent requests.
* Finally, because connections are not proxied through the load balancer for DNS only, certain steering methods will not work either. For example, [LORS](#least-outstanding-requests-steering-lors) will not work since Cloudflare will not be aware of the connections to the endpoints. These steering methods will revert to random weighted steering.

For more information on additional steering methods, please refer to the [Steering](#steering) section.

There are also client and resolver DNS cache considerations when using DNS-only load balancers. The cache life is determined by the DNS server answering the request. The [Time-to-Live (TTL) ↗](https://www.cloudflare.com/learning/cdn/glossary/time-to-live-ttl/) value tells a DNS requester how long the response is valid before the client should send a new DNS request to see if the destination has changed. The TTL is calculated in seconds, so — for example — a TTL value of 3600 equates to a TTL of one hour. However, standard DNS TTL values are usually either 12 or 24 hours or 43200 and 86400 respectively.

The TTL of a DNS-only load balancer is set to 30 (seconds). This ensures that as endpoint health changes or endpoints are added or deleted, the DNS-only load balancer is queried more often to provide the most accurate list of available endpoints possible.

**Important notes about DNS-only load balancers:**

* DNS-only load balancers support only public endpoints
* DNS-only load balancers do not proxy traffic — and — as such, are not involved in the connections to endpoint
* DNS-only load balancers only respond to a DNS request with an IP address or set of IP addresses

##### Spectrum load balancing

Cloudflare also offers another ingress method via the [Spectrum](https://developers.cloudflare.com/spectrum/) product.

Where the layer 7 stack only supported HTTP(S) and WebSockets, Spectrum offers support for any TCP- or UDP-based protocol. A Cloudflare Load Balancer using Spectrum as an ingress for traffic operates at layer 4, where both TCP and UDP protocols exist. Any service that utilizes TCP or UDP for transport can leverage Spectrum with a Cloudflare Load Balancer including SSH, FTP, NTP, SMTP, and more.

Given the breadth of services and protocols this represents, the treatment provided is more generalized than what is offered with the layer 7 HTTP(S) stack. For example, Cloudflare Spectrum supports features such as TLS/SSL offloading, DDoS protection, IP Access lists, Argo Smart Routing, and session persistence with our layer 4 load balancers.

![Spectrum-based load balancing supports public endpoints](https://developers.cloudflare.com/_astro/lb-ref-arch-28-ALT.Dwf-s8s__1kYKMO.svg "Figure 28: Spectrum Layer 4 load balancers support both TCP and UDP protocols")

Figure 28: Spectrum Layer 4 load balancers support both TCP and UDP protocols

Cloudflare layer 4 Spectrum load balancers are publicly accessible. Access to these load balancing resources can be managed using a Spectrum configuration called _IP Access Rules,_ which can be defined as part of a WAF configuration, but are limited to rules created with the “allow” or “block” action for specific IP addresses, subnets, countries, or [Border Gateway Protocol (BGP) ↗](https://www.cloudflare.com/learning/security/glossary/what-is-bgp/) Autonomous System Numbers (ASNs).

In addition to being public, Spectrum load balancers are always proxied. The proxy setting shown earlier (Figures 24 and 25) will be ignored when Spectrum is configured as the ingress path for the load balancer. All traffic destined for Spectrum-based load balancers will always pass through the Cloudflare edge.

**Important notes about Spectrum load balancers:**

* Spectrum load balancers support both public and private endpoints
* Spectrum load balancers are initially created as Layer 7 HTTP(S) load balancers. A Spectrum application is then created with a Load Balancer endpoint type, and the load balancer that has already been created is selected.
* Spectrum load balancers are always proxied, regardless of the proxy setting on the load balancer configuration
* There is no ability to change the ingress port from the Internet via Spectrum to the endpoint; i.e., if the traffic comes in on port 22 to Spectrum, it will be steered to port 22 on the endpoint
* Spectrum load balancers only support session affinity using the hash endpoint steering method
* Spectrum load balancers do not support Custom Rules

##### Deployment models at-a-glance

| Load Balancer Model | Public | Proxied | OSI Layer | Traffic Type |
| ------------------- | ------ | ------- | --------- | ------------ |
| Layer 7 HTTP(S)     | X      | X       | 7         | HTTP(S)      |
| DNS-Only            | X      | 7 (DNS) | IP-Based  |              |
| Spectrum            | X      | X       | 4         | TCP/UDP      |

#### Load balancer details

##### Hostname

The hostname setting is the publicly-reachable hostname for the load balancer. The hostname must be created within the zone for which the load balancer is being created.

##### Proxy status

The proxy setting determines whether Cloudflare will proxy traffic for the load balancer or simply provide a DNS reply with the endpoints for the client to directly connect. This is covered in detail in the [Deployment models](#deployment-models) section.

##### Session affinity

Session affinity, also known as session persistence or sticky sessions, keeps a client connected to the same endpoint for all subsequent requests after the first request or connection. This can be an important feature for applications that don’t share session data — the context of a user’s interaction with a web application — between endpoints. For example, if a new endpoint were selected in the middle of a client session and information about the session (e.g. the contents of a user’s shopping cart) were lost, the user experience for that application would be poor.

Cloudflare offers three methods for enabling session affinity:

1. **By Cloudflare cookie only (cookie):** On the first request to a proxied load balancer, a cookie is generated, encoding information of which endpoint the request will be forwarded to. Subsequent requests (by the same client to the same load balancer) will be sent to the endpoint that the cookie encodes for a) the duration of the cookie and b) as long as the endpoint remains healthy. If the cookie has expired or the endpoint is unhealthy, a new endpoint will be calculated and used.
2. **By Cloudflare cookie and Client IP fallback (ip\_cookie):** This behaves similar to the cookie method above, except that the cookie is generated based on the client IP address. In this case, requests from the same IP address always get steered towards the same endpoint for a) the duration of the cookie and b) as long as the endpoint remains healthy. If the cookie has expired or the endpoint is unhealthy, a new endpoint will be calculated and used.
3. **By HTTP header (header):** On the first request to a proxied load balancer, a session key is generated based on the configured HTTP headers. Subsequent requests to the load balancer with the same headers will be sent to the same endpoint, for a) the duration of the session or b) as long as the endpoint remains healthy. If the session has been idle for the duration of session affinity time-to-live (TTL) seconds or the endpoint is unhealthy, then a new endpoint will be calculated and used.

These three session affinity options only apply to layer 7 HTTP(S) load balancers. Session affinity requires a TTL, which determines how long the load balancer will route subsequent requests to a specific endpoint. The default TTL is 82,800 seconds (23 hours), but it can be set for anywhere from 1,800 seconds (30 minutes) to 604,800 seconds (seven days).

For cookie-based session affinity, the expiration timer is never reset, meaning that the timer is counting down from the start of the session — regardless of the session being idle or active. HTTP header-based session affinity will reset the expiration timer every time there is activity in the session.

##### Endpoint draining

Endpoint draining is a subfeature of session affinity. It allows for sessions to gracefully expire from an endpoint while not allowing new sessions to be created on that same endpoint. Endpoint draining is useful for maintenance, as it does not require administrators to arbitrarily or abruptly cut off user sessions in order to remove all active sessions from an endpoint.

The endpoint drain TTL is the amount of time that endpoints will be allowed to maintain active sessions before being forcefully terminated. Once the endpoint drain TTL is set, endpoint draining is started by disabling an endpoint (or multiple endpoints) within an endpoint pool. As seen in the below image, administrators can monitor the time remaining on an endpoint drawing operation from the load balancer UI.

![Endpoint draining in process from web user interface](https://developers.cloudflare.com/_astro/lb-ref-arch-30.todYN9Ax_1LLmJE.webp "Figure 30: Endpoint draining occurring within a Cloudflare Load Balancer")

Figure 30: Endpoint draining occurring within a Cloudflare Load Balancer

Endpoint draining is only applicable for session affinity because without session affinity, subsequent requests or connections are not guaranteed to be steered to the same endpoint. Thus, disabling an endpoint does not have an impact on user experience.

##### Zero-downtime failover

Zero-downtime failover automatically sends traffic to endpoints within an endpoint pool during transient network issues. 

Zero-downtime failover will trigger a single retry only if there is another healthy endpoint in the pool and a [521, 522, 523, 525 or 526 error code](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-521/) is occurring. No other error codes will trigger a zero-downtime failover operation.

These response codes are not returned from the endpoint, but from requests made by upstream Cloudflare services to an organization's endpoints. 

Zero-downtime failover has three modes of operation:

1. **None (Off):** No failover will take place and users may receive error messages or a poor user experience.
2. **Temporary:** Traffic will be sent to other endpoint(s) until the endpointal endpoint is available again.
3. **Sticky:** The session affinity cookie is updated and subsequent requests are sent to the new endpoint moving forward as needed. This is not supported when session affinity is using HTTP header mode.

##### Adaptive routing - failover across pools

_Adaptive routing - failover across pools_ extends the functionality of zero-downtime failover by allowing failover to extend to endpoints in another endpoint pool, rather than only failing over to an endpoint in the _same_ pool.

##### Endpoint pools

Endpoint pools are configured in a priority order and can be rearranged as needed. This priority order is only considered when using _Off - Failover traffic steering;_ otherwise, endpoint pools will be selected based on the criteria outlined in the [Steering methods](#steering-methods) section.

The endpoint pools assigned to a load balancer represent the entire collection of endpoints that could possibly handle requests or connections through the load balancer. An endpoint pool typically contains endpoints that all have the same capabilities and are in the data center or geographic region. All endpoints in a pool should be capable of handling any request directed to an endpoint pool. For more information about endpoint pools, please refer to the [Endpoint pools](#endpoint-pools) section.

##### Fallback pools

A fallback pool is the pool of last resort. When all endpoint pools are unavailable or unhealthy, the fallback pool will be used for all requests and connections. While health monitor data is always considered when steering traffic within a load balancer, a fallback pool does not rely on this data and is not subject to it.

##### Health monitors

Health monitors are usually configured as part of the endpoint pool. Health monitors can be added, changed, or deleted as part of the load balancer configuration. Please see the [Health monitors](#health-monitors) section for more information.

##### Traffic steering

Traffic steering is the method of steering between endpoint pools. For help understanding which traffic steering method to select, please see the [Steering types and methods](#steering-types-and-methods) section.

##### Custom rules

[Custom rules](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/) allow users to perform actions on requests or connections before the load balancer finishes its decision process. Custom rules are configured with expressions that match certain [fields](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/reference/) in requests or connections. Once the expression is created to match traffic, an [action](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/actions/) is assigned for when a request or connection matches the expression.

Custom rules are a powerful tool for customizing the steering and output from a load balancer before the request or connection is sent to the endpoint. For example, the HTTP method (e.g. GET, PUT, POST) could be matched to ensure that POST messages are sent to a specific endpoint pool dedicated to handling receiving information from clients.

Alternatively, that session affinity TTL could be reset based on a request going to a specific URL path to ensure that the client has enough time to complete the transaction.

It is not possible to document all of the potential combinations of fields that can be matched and actions that can be taken. However, the following resources describe all of the fields and actions that are currently available:

* [Supported fields and operators](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/reference/)
* [Load Balancing actions](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/actions/)

If the default behavior of a load balancer is not covered in the documents listed above, it is likely that a custom rule can help meet unique use case requirements.

### Protecting and securing load balancers

#### Inherent security

All Cloudflare Load Balancer deployment models come with inherent protections. The following section briefly highlights the default security Cloudflare provides, as well as optional protections that can be added in front of Cloudflare Load Balancers:

* Proxied HTTP layer 7 load balancer (Public)  
   * [DDoS protection](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/) to protect against attacks  
   * WAF with [Cloudflare managed ruleset](https://developers.cloudflare.com/waf/managed-rules/reference/cloudflare-managed-ruleset/) and [OWASP ruleset](https://developers.cloudflare.com/waf/managed-rules/reference/owasp-core-ruleset/) to block known vulnerabilities and exploits
* DNS-only load balancer (Public)  
   * [DNS DDoS protection ↗](https://www.cloudflare.com/learning/cdn/glossary/anycast-network/) to ensure a DNS-only load balancer is always available
* Spectrum layer 4 load balancer (Public)  
   * [DDoS Protection](https://developers.cloudflare.com/spectrum/about/ddos-for-spectrum/) to protect against layer 4 attacks

#### Additional options

Cloudflare offers additional security layers that can be used in conjunction with load balancing to protect any services — including websites, APIs, HTTP(S)-based services, and more:

* Proxied HTTP layer 7 load balancer (Public)  
   * [Bot management](https://developers.cloudflare.com/bots/) to control which bots can access resources  
   * [WAF](https://developers.cloudflare.com/waf/) for creating custom rules for web applications  
   * [Client-side security](https://developers.cloudflare.com/client-side-security/) for monitoring script usage on web applications  
   * [API Shield](https://developers.cloudflare.com/api-shield/) for protecting APIs
* DNS-only load balancer (Public)  
   * [DNSSEC](https://developers.cloudflare.com/dns/dnssec/) to ensure authenticity of DNS records
* Spectrum layer 4 load balancer (Public)  
   * [IP Access Rules](https://developers.cloudflare.com/spectrum/reference/configuration-options/#ip-access-rules) for controlling access to public layer 4 load balancers

## Summary

The Cloudflare global anycast network is a powerful platform for load balancing. A load balancing configuration in Cloudflare is accessible in over 330 cities across the world and has virtually unlimited capacity and bandwidth.

These load balancers operate within approximately 50ms of about 95% of the Internet-connected population, including endpoints that allow Cloudflare Load Balancers to perform both GTM and Private Network Load Balancing. Cloudflare now combines these two distinct load balancing concepts into a single load balancer. This helps enable organizations to steer traffic to geographically-relevant data centers, then select the proper endpoint to handle the request.

With Cloudflare Tunnel, endpoints can be located within private networks and still be utilized by Cloudflare Load Balancers. Cloudflare offers public layer 7 load balancers — that supports both HTTP(S) and WebSockets, as well as public layer 4 load balancers that can steer any TCP or UDP traffic. This means that Cloudflare can offer load balancing services to all organizations and users, no matter their location, use cases, or existing configurations.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/reference-architecture/","name":"Reference Architecture"}},{"@type":"ListItem","position":3,"item":{"@id":"/reference-architecture/architectures/","name":"Reference Architectures"}},{"@type":"ListItem","position":4,"item":{"@id":"/reference-architecture/architectures/load-balancing/","name":"Load Balancing Reference Architecture"}}]}
```

---

## Load Balancer Details

**get** `/zones/{zone_id}/load_balancers/{load_balancer_id}`

Fetch a single configured load balancer.

### Path Parameters

- `zone_id: string`

- `load_balancer_id: string`

### Returns

- `errors: array of ResponseInfo`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of ResponseInfo`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

- `result: LoadBalancer`

  - `id: optional string`

  - `adaptive_routing: optional AdaptiveRouting`

    Controls features that modify the routing of requests to pools and origins in response to dynamic conditions, such as during the interval between active health monitoring requests. For example, zero-downtime failover occurs immediately when an origin becomes unavailable due to HTTP 521, 522, or 523 response codes. If there is another healthy origin in the same pool, the request is retried once against this alternate origin.

    - `failover_across_pools: optional boolean`

      Extends zero-downtime failover of requests to healthy origins from alternate pools, when no healthy alternate exists in the same pool, according to the failover order defined by traffic and origin steering. When set false (the default) zero-downtime failover will only occur between origins within the same pool. See `session_affinity_attributes` for control over when sessions are broken or reassigned.

  - `country_pools: optional map[array of string]`

    A mapping of country codes to a list of pool IDs (ordered by their failover priority) for the given country. Any country not explicitly defined will fall back to using the corresponding region_pool mapping if it exists else to default_pools.

  - `created_on: optional string`

  - `default_pools: optional array of DefaultPools`

    A list of pool IDs ordered by their failover priority. Pools defined here are used by default, or when region_pools are not configured for a given region.

  - `description: optional string`

    Object description.

  - `enabled: optional boolean`

    Whether to enable (the default) this load balancer.

  - `fallback_pool: optional string`

    The pool ID to use when all other pools are detected as unhealthy.

  - `location_strategy: optional LocationStrategy`

    Controls location-based steering for non-proxied requests. See `steering_policy` to learn how steering is affected.

    - `mode: optional "pop" or "resolver_ip"`

      Determines the authoritative location when ECS is not preferred, does not exist in the request, or its GeoIP lookup is unsuccessful.

      - `"pop"`: Use the Cloudflare PoP location.
      - `"resolver_ip"`: Use the DNS resolver GeoIP location. If the GeoIP lookup is unsuccessful, use the Cloudflare PoP location.

      - `"pop"`

      - `"resolver_ip"`

    - `prefer_ecs: optional "always" or "never" or "proximity" or "geo"`

      Whether the EDNS Client Subnet (ECS) GeoIP should be preferred as the authoritative location.

      - `"always"`: Always prefer ECS.
      - `"never"`: Never prefer ECS.
      - `"proximity"`: Prefer ECS only when `steering_policy="proximity"`.
      - `"geo"`: Prefer ECS only when `steering_policy="geo"`.

      - `"always"`

      - `"never"`

      - `"proximity"`

      - `"geo"`

  - `modified_on: optional string`

  - `name: optional string`

    The DNS hostname to associate with your Load Balancer. If this hostname already exists as a DNS record in Cloudflare's DNS, the Load Balancer will take precedence and the DNS record will not be used.

  - `networks: optional array of string`

    List of networks where Load Balancer or Pool is enabled.

  - `pop_pools: optional map[array of string]`

    Enterprise only: A mapping of Cloudflare PoP identifiers to a list of pool IDs (ordered by their failover priority) for the PoP (datacenter). Any PoPs not explicitly defined will fall back to using the corresponding country_pool, then region_pool mapping if it exists else to default_pools.

  - `proxied: optional boolean`

    Whether the hostname should be gray clouded (false) or orange clouded (true).

  - `random_steering: optional RandomSteering`

    Configures pool weights.

    - `steering_policy="random"`: A random pool is selected with probability proportional to pool weights.
    - `steering_policy="least_outstanding_requests"`: Use pool weights to scale each pool's outstanding requests.
    - `steering_policy="least_connections"`: Use pool weights to scale each pool's open connections.

    - `default_weight: optional number`

      The default weight for pools in the load balancer that are not specified in the pool_weights map.

    - `pool_weights: optional map[number]`

      A mapping of pool IDs to custom weights. The weight is relative to other pools in the load balancer.

  - `region_pools: optional map[array of string]`

    A mapping of region codes to a list of pool IDs (ordered by their failover priority) for the given region. Any regions not explicitly defined will fall back to using default_pools.

  - `rules: optional array of Rules`

    BETA Field Not General Access: A list of rules for this load balancer to execute.

    - `condition: optional string`

      The condition expressions to evaluate. If the condition evaluates to true, the overrides or fixed_response in this rule will be applied. An empty condition is always true. For more details on condition expressions, please see https://developers.cloudflare.com/load-balancing/understand-basics/load-balancing-rules/expressions.

    - `disabled: optional boolean`

      Disable this specific rule. It will no longer be evaluated by this load balancer.

    - `fixed_response: optional object { content_type, location, message_body, status_code }`

      A collection of fields used to directly respond to the eyeball instead of routing to a pool. If a fixed_response is supplied the rule will be marked as terminates.

      - `content_type: optional string`

        The http 'Content-Type' header to include in the response.

      - `location: optional string`

        The http 'Location' header to include in the response.

      - `message_body: optional string`

        Text to include as the http body.

      - `status_code: optional number`

        The http status code to respond with.

    - `name: optional string`

      Name of this rule. Only used for human readability.

    - `overrides: optional object { adaptive_routing, country_pools, default_pools, 10 more }`

      A collection of overrides to apply to the load balancer when this rule's condition is true. All fields are optional.

      - `adaptive_routing: optional AdaptiveRouting`

        Controls features that modify the routing of requests to pools and origins in response to dynamic conditions, such as during the interval between active health monitoring requests. For example, zero-downtime failover occurs immediately when an origin becomes unavailable due to HTTP 521, 522, or 523 response codes. If there is another healthy origin in the same pool, the request is retried once against this alternate origin.

      - `country_pools: optional map[array of string]`

        A mapping of country codes to a list of pool IDs (ordered by their failover priority) for the given country. Any country not explicitly defined will fall back to using the corresponding region_pool mapping if it exists else to default_pools.

      - `default_pools: optional array of DefaultPools`

        A list of pool IDs ordered by their failover priority. Pools defined here are used by default, or when region_pools are not configured for a given region.

      - `fallback_pool: optional string`

        The pool ID to use when all other pools are detected as unhealthy.

      - `location_strategy: optional LocationStrategy`

        Controls location-based steering for non-proxied requests. See `steering_policy` to learn how steering is affected.

      - `pop_pools: optional map[array of string]`

        Enterprise only: A mapping of Cloudflare PoP identifiers to a list of pool IDs (ordered by their failover priority) for the PoP (datacenter). Any PoPs not explicitly defined will fall back to using the corresponding country_pool, then region_pool mapping if it exists else to default_pools.

      - `random_steering: optional RandomSteering`

        Configures pool weights.

        - `steering_policy="random"`: A random pool is selected with probability proportional to pool weights.
        - `steering_policy="least_outstanding_requests"`: Use pool weights to scale each pool's outstanding requests.
        - `steering_policy="least_connections"`: Use pool weights to scale each pool's open connections.

      - `region_pools: optional map[array of string]`

        A mapping of region codes to a list of pool IDs (ordered by their failover priority) for the given region. Any regions not explicitly defined will fall back to using default_pools.

      - `session_affinity: optional SessionAffinity`

        Specifies the type of session affinity the load balancer should use unless specified as `"none"`. The supported types are: - `"cookie"`: On the first request to a proxied load balancer, a cookie is generated, encoding information of which origin the request will be forwarded to. Subsequent requests, by the same client to the same load balancer, will be sent to the origin server the cookie encodes, for the duration of the cookie and as long as the origin server remains healthy. If the cookie has expired or the origin server is unhealthy, then a new origin server is calculated and used. - `"ip_cookie"`: Behaves the same as `"cookie"` except the initial origin selection is stable and based on the client's ip address. - `"header"`: On the first request to a proxied load balancer, a session key based on the configured HTTP headers (see `session_affinity_attributes.headers`) is generated, encoding the request headers used for storing in the load balancer session state which origin the request will be forwarded to. Subsequent requests to the load balancer with the same headers will be sent to the same origin server, for the duration of the session and as long as the origin server remains healthy. If the session has been idle for the duration of `session_affinity_ttl` seconds or the origin server is unhealthy, then a new origin server is calculated and used. See `headers` in `session_affinity_attributes` for additional required configuration.

        - `"none"`

        - `"cookie"`

        - `"ip_cookie"`

        - `"header"`

      - `session_affinity_attributes: optional SessionAffinityAttributes`

        Configures attributes for session affinity.

        - `drain_duration: optional number`

          Configures the drain duration in seconds. This field is only used when session affinity is enabled on the load balancer.

        - `headers: optional array of string`

          Configures the names of HTTP headers to base session affinity on when header `session_affinity` is enabled. At least one HTTP header name must be provided. To specify the exact cookies to be used, include an item in the following format: `"cookie:<cookie-name-1>,<cookie-name-2>"` (example) where everything after the colon is a comma-separated list of cookie names. Providing only `"cookie"` will result in all cookies being used. The default max number of HTTP header names that can be provided depends on your plan: 5 for Enterprise, 1 for all other plans.

        - `require_all_headers: optional boolean`

          When header `session_affinity` is enabled, this option can be used to specify how HTTP headers on load balancing requests will be used. The supported values are: - `"true"`: Load balancing requests must contain *all* of the HTTP headers specified by the `headers` session affinity attribute, otherwise sessions aren't created. - `"false"`: Load balancing requests must contain *at least one* of the HTTP headers specified by the `headers` session affinity attribute, otherwise sessions aren't created.

        - `samesite: optional "Auto" or "Lax" or "None" or "Strict"`

          Configures the SameSite attribute on session affinity cookie. Value "Auto" will be translated to "Lax" or "None" depending if Always Use HTTPS is enabled. Note: when using value "None", the secure attribute can not be set to "Never".

          - `"Auto"`

          - `"Lax"`

          - `"None"`

          - `"Strict"`

        - `secure: optional "Auto" or "Always" or "Never"`

          Configures the Secure attribute on session affinity cookie. Value "Always" indicates the Secure attribute will be set in the Set-Cookie header, "Never" indicates the Secure attribute will not be set, and "Auto" will set the Secure attribute depending if Always Use HTTPS is enabled.

          - `"Auto"`

          - `"Always"`

          - `"Never"`

        - `zero_downtime_failover: optional "none" or "temporary" or "sticky"`

          Configures the zero-downtime failover between origins within a pool when session affinity is enabled. This feature is currently incompatible with Argo, Tiered Cache, and Bandwidth Alliance. The supported values are: - `"none"`: No failover takes place for sessions pinned to the origin (default). - `"temporary"`: Traffic will be sent to another other healthy origin until the originally pinned origin is available; note that this can potentially result in heavy origin flapping. - `"sticky"`: The session affinity cookie is updated and subsequent requests are sent to the new origin. Note: Zero-downtime failover with sticky sessions is currently not supported for session affinity by header.

          - `"none"`

          - `"temporary"`

          - `"sticky"`

      - `session_affinity_ttl: optional number`

        Time, in seconds, until a client's session expires after being created. Once the expiry time has been reached, subsequent requests may get sent to a different origin server. The accepted ranges per `session_affinity` policy are: - `"cookie"` / `"ip_cookie"`: The current default of 23 hours will be used unless explicitly set. The accepted range of values is between [1800, 604800]. - `"header"`: The current default of 1800 seconds will be used unless explicitly set. The accepted range of values is between [30, 3600]. Note: With session affinity by header, sessions only expire after they haven't been used for the number of seconds specified.

      - `steering_policy: optional SteeringPolicy`

        Steering Policy for this load balancer.

        - `"off"`: Use `default_pools`.
        - `"geo"`: Use `region_pools`/`country_pools`/`pop_pools`. For non-proxied requests, the country for `country_pools` is determined by `location_strategy`.
        - `"random"`: Select a pool randomly.
        - `"dynamic_latency"`: Use round trip time to select the closest pool in default_pools (requires pool health checks).
        - `"proximity"`: Use the pools' latitude and longitude to select the closest pool using the Cloudflare PoP location for proxied requests or the location determined by `location_strategy` for non-proxied requests.
        - `"least_outstanding_requests"`: Select a pool by taking into consideration `random_steering` weights, as well as each pool's number of outstanding requests. Pools with more pending requests are weighted proportionately less relative to others.
        - `"least_connections"`: Select a pool by taking into consideration `random_steering` weights, as well as each pool's number of open connections. Pools with more open connections are weighted proportionately less relative to others. Supported for HTTP/1 and HTTP/2 connections.
        - `""`: Will map to `"geo"` if you use `region_pools`/`country_pools`/`pop_pools` otherwise `"off"`.

        - `"off"`

        - `"geo"`

        - `"random"`

        - `"dynamic_latency"`

        - `"proximity"`

        - `"least_outstanding_requests"`

        - `"least_connections"`

        - `""`

      - `ttl: optional number`

        Time to live (TTL) of the DNS entry for the IP address returned by this load balancer. This only applies to gray-clouded (unproxied) load balancers.

    - `priority: optional number`

      The order in which rules should be executed in relation to each other. Lower values are executed first. Values do not need to be sequential. If no value is provided for any rule the array order of the rules field will be used to assign a priority.

    - `terminates: optional boolean`

      If this rule's condition is true, this causes rule evaluation to stop after processing this rule.

  - `session_affinity: optional SessionAffinity`

    Specifies the type of session affinity the load balancer should use unless specified as `"none"`. The supported types are: - `"cookie"`: On the first request to a proxied load balancer, a cookie is generated, encoding information of which origin the request will be forwarded to. Subsequent requests, by the same client to the same load balancer, will be sent to the origin server the cookie encodes, for the duration of the cookie and as long as the origin server remains healthy. If the cookie has expired or the origin server is unhealthy, then a new origin server is calculated and used. - `"ip_cookie"`: Behaves the same as `"cookie"` except the initial origin selection is stable and based on the client's ip address. - `"header"`: On the first request to a proxied load balancer, a session key based on the configured HTTP headers (see `session_affinity_attributes.headers`) is generated, encoding the request headers used for storing in the load balancer session state which origin the request will be forwarded to. Subsequent requests to the load balancer with the same headers will be sent to the same origin server, for the duration of the session and as long as the origin server remains healthy. If the session has been idle for the duration of `session_affinity_ttl` seconds or the origin server is unhealthy, then a new origin server is calculated and used. See `headers` in `session_affinity_attributes` for additional required configuration.

  - `session_affinity_attributes: optional SessionAffinityAttributes`

    Configures attributes for session affinity.

  - `session_affinity_ttl: optional number`

    Time, in seconds, until a client's session expires after being created. Once the expiry time has been reached, subsequent requests may get sent to a different origin server. The accepted ranges per `session_affinity` policy are: - `"cookie"` / `"ip_cookie"`: The current default of 23 hours will be used unless explicitly set. The accepted range of values is between [1800, 604800]. - `"header"`: The current default of 1800 seconds will be used unless explicitly set. The accepted range of values is between [30, 3600]. Note: With session affinity by header, sessions only expire after they haven't been used for the number of seconds specified.

  - `steering_policy: optional SteeringPolicy`

    Steering Policy for this load balancer.

    - `"off"`: Use `default_pools`.
    - `"geo"`: Use `region_pools`/`country_pools`/`pop_pools`. For non-proxied requests, the country for `country_pools` is determined by `location_strategy`.
    - `"random"`: Select a pool randomly.
    - `"dynamic_latency"`: Use round trip time to select the closest pool in default_pools (requires pool health checks).
    - `"proximity"`: Use the pools' latitude and longitude to select the closest pool using the Cloudflare PoP location for proxied requests or the location determined by `location_strategy` for non-proxied requests.
    - `"least_outstanding_requests"`: Select a pool by taking into consideration `random_steering` weights, as well as each pool's number of outstanding requests. Pools with more pending requests are weighted proportionately less relative to others.
    - `"least_connections"`: Select a pool by taking into consideration `random_steering` weights, as well as each pool's number of open connections. Pools with more open connections are weighted proportionately less relative to others. Supported for HTTP/1 and HTTP/2 connections.
    - `""`: Will map to `"geo"` if you use `region_pools`/`country_pools`/`pop_pools` otherwise `"off"`.

  - `ttl: optional number`

    Time to live (TTL) of the DNS entry for the IP address returned by this load balancer. This only applies to gray-clouded (unproxied) load balancers.

  - `zone_name: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

### Example

```http
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/load_balancers/$LOAD_BALANCER_ID \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "result": {
    "id": "699d98642c564d2e855e9661899b7252",
    "adaptive_routing": {
      "failover_across_pools": true
    },
    "country_pools": {
      "GB": [
        "abd90f38ced07c2e2f4df50b1f61d4194"
      ],
      "US": [
        "de90f38ced07c2e2f4df50b1f61d4194",
        "00920f38ce07c2e2f4df50b1f61d4194"
      ]
    },
    "created_on": "2014-01-01T05:20:00.12345Z",
    "default_pools": [
      "17b5962d775c646f3f9725cbc7a53df4",
      "9290f38c5d07c2e2f4df57b1f61d4196",
      "00920f38ce07c2e2f4df50b1f61d4194"
    ],
    "description": "Load Balancer for www.example.com",
    "enabled": true,
    "fallback_pool": "fallback_pool",
    "location_strategy": {
      "mode": "resolver_ip",
      "prefer_ecs": "always"
    },
    "modified_on": "2014-01-01T05:20:00.12345Z",
    "name": "www.example.com",
    "networks": [
      "string"
    ],
    "pop_pools": {
      "LAX": [
        "de90f38ced07c2e2f4df50b1f61d4194",
        "9290f38c5d07c2e2f4df57b1f61d4196"
      ],
      "LHR": [
        "abd90f38ced07c2e2f4df50b1f61d4194",
        "f9138c5d07c2e2f4df57b1f61d4196"
      ],
      "SJC": [
        "00920f38ce07c2e2f4df50b1f61d4194"
      ]
    },
    "proxied": true,
    "random_steering": {
      "default_weight": 0.2,
      "pool_weights": {
        "9290f38c5d07c2e2f4df57b1f61d4196": 0.5,
        "de90f38ced07c2e2f4df50b1f61d4194": 0.3
      }
    },
    "region_pools": {
      "ENAM": [
        "00920f38ce07c2e2f4df50b1f61d4194"
      ],
      "WNAM": [
        "de90f38ced07c2e2f4df50b1f61d4194",
        "9290f38c5d07c2e2f4df57b1f61d4196"
      ]
    },
    "rules": [
      {
        "condition": "http.request.uri.path contains \"/testing\"",
        "disabled": true,
        "fixed_response": {
          "content_type": "application/json",
          "location": "www.example.com",
          "message_body": "Testing Hello",
          "status_code": 0
        },
        "name": "route the path /testing to testing datacenter.",
        "overrides": {
          "adaptive_routing": {
            "failover_across_pools": true
          },
          "country_pools": {
            "GB": [
              "abd90f38ced07c2e2f4df50b1f61d4194"
            ],
            "US": [
              "de90f38ced07c2e2f4df50b1f61d4194",
              "00920f38ce07c2e2f4df50b1f61d4194"
            ]
          },
          "default_pools": [
            "17b5962d775c646f3f9725cbc7a53df4",
            "9290f38c5d07c2e2f4df57b1f61d4196",
            "00920f38ce07c2e2f4df50b1f61d4194"
          ],
          "fallback_pool": "fallback_pool",
          "location_strategy": {
            "mode": "resolver_ip",
            "prefer_ecs": "always"
          },
          "pop_pools": {
            "LAX": [
              "de90f38ced07c2e2f4df50b1f61d4194",
              "9290f38c5d07c2e2f4df57b1f61d4196"
            ],
            "LHR": [
              "abd90f38ced07c2e2f4df50b1f61d4194",
              "f9138c5d07c2e2f4df57b1f61d4196"
            ],
            "SJC": [
              "00920f38ce07c2e2f4df50b1f61d4194"
            ]
          },
          "random_steering": {
            "default_weight": 0.2,
            "pool_weights": {
              "9290f38c5d07c2e2f4df57b1f61d4196": 0.5,
              "de90f38ced07c2e2f4df50b1f61d4194": 0.3
            }
          },
          "region_pools": {
            "ENAM": [
              "00920f38ce07c2e2f4df50b1f61d4194"
            ],
            "WNAM": [
              "de90f38ced07c2e2f4df50b1f61d4194",
              "9290f38c5d07c2e2f4df57b1f61d4196"
            ]
          },
          "session_affinity": "cookie",
          "session_affinity_attributes": {
            "drain_duration": 100,
            "headers": [
              "x"
            ],
            "require_all_headers": true,
            "samesite": "Auto",
            "secure": "Auto",
            "zero_downtime_failover": "sticky"
          },
          "session_affinity_ttl": 1800,
          "steering_policy": "dynamic_latency",
          "ttl": 30
        },
        "priority": 0,
        "terminates": true
      }
    ],
    "session_affinity": "cookie",
    "session_affinity_attributes": {
      "drain_duration": 100,
      "headers": [
        "x"
      ],
      "require_all_headers": true,
      "samesite": "Auto",
      "secure": "Auto",
      "zero_downtime_failover": "sticky"
    },
    "session_affinity_ttl": 1800,
    "steering_policy": "dynamic_latency",
    "ttl": 30,
    "zone_name": "example.com"
  },
  "success": true
}
```

---

---
title: Changelog
description: Track the latest updates and changes to Load Balancing features.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Changelog

[ Subscribe to RSS ](https://developers.cloudflare.com/changelog/rss/load-balancing.xml) 

## 2025-10-16

  
**Monitor Groups for Advanced Health Checking With Load Balancing**   

Cloudflare Load Balancing now supports Monitor Groups, a powerful new way to combine multiple health monitors into a single, logical group. This allows you to create sophisticated health checks that more accurately reflect the true availability of your applications by assessing multiple services at once.

With Monitor Groups, you can ensure that all critical components of an application are healthy before sending traffic to an origin pool, enabling smarter failover decisions and greater resilience. This feature is now available via the API for customers with an Enterprise Load Balancing subscription.

#### What you can do:

* **Combine Multiple Monitors**: Group different health monitors (for example, HTTP, TCP) that check various application components, like a primary API gateway and a specific `/login` service.
* **Isolate Monitors for Observation**: Mark a monitor as "monitoring only" to receive alerts and data without it affecting a pool's health status or traffic steering. This is perfect for testing new checks or observing non-critical dependencies.
* **Improve Steering Intelligence**: Latency for Dynamic Steering is automatically averaged across all active monitors in a group, providing a more holistic view of an origin's performance.

This enhancement is ideal for complex, multi-service applications where the health of one component depends on another. By aggregating health signals, Monitor Groups provide a more accurate and comprehensive assessment of your application's true status.

For detailed information and API configuration guides, please visit our [developer documentation](https://developers.cloudflare.com/load-balancing/monitors/monitor-groups) for Monitor Groups.

## 2025-08-15

  
**Steer Traffic by AS Number in Load Balancing Custom Rules**   

You can now create more granular, network-aware Custom Rules in Cloudflare Load Balancing using the Autonomous System Number (ASN) of an incoming request.

This allows you to steer traffic with greater precision based on the network source of a request. For example, you can route traffic from specific Internet Service Providers (ISPs) or enterprise customers to dedicated infrastructure, optimize performance, or enforce compliance by directing certain networks to preferred data centers.

![Create a Load Balancing Custom Rule using AS Num](https://developers.cloudflare.com/_astro/asnum-custom-rule.CtcHu_zj_Z24vRO0.webp) 

To get started, create a [Custom Rule ↗](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/) in your Load Balancer and select **AS Num** from the **Field** dropdown.

## 2025-08-06

  
**Improvements to Monitoring Using Zone Settings**   

Cloudflare Load Balancing Monitors support loading and applying settings for a specific zone to monitoring requests to origin endpoints. This feature has been migrated to new infrastructure to improve reliability, performance, and accuracy.

All zone monitors have been tested against the new infrastructure. There should be no change to health monitoring results of currently healthy and active pools. Newly created or re-enabled pools may need validation of their monitor zone settings before being introduced to service, especially regarding correct application of mTLS.

#### What you can expect:

* More reliable application of zone settings to monitoring requests, including  
   * Authenticated Origin Pulls  
   * Aegis Egress IP Pools  
   * Argo Smart Routing  
   * HTTP/2 to Origin
* Improved support and bug fixes for retries, redirects, and proxied origin resolution
* Improved performance and reliability of monitoring requests within the Cloudflare network
* Unrelated CDN or WAF configuration changes should have no risk of impact to pool health

## 2025-06-04

  
**New Account-Level Load Balancing UI and Private Load Balancers**   

We've made two large changes to load balancing:

* Redesigned the user interface, now centralized at the **account level**.
* Introduced [**Private Load Balancers**](https://developers.cloudflare.com/load-balancing/private-network/) to the UI, enabling you to manage traffic for all of your external and internal applications in a single spot.

This update streamlines how you manage load balancers across multiple zones and extends robust traffic management to your private network infrastructure.

![Load Balancing UI](https://developers.cloudflare.com/_astro/account-load-balancing-ui.CoCi7gPb_Z2rDoCY.webp) 

**Key Enhancements:**

* **Account-Level UI Consolidation:**  
   * **Unified Management:** Say goodbye to navigating individual zones for load balancing tasks. You can now view, configure, and monitor all your load balancers across every zone in your account from a single, intuitive interface at the account level.  
   * **Improved Efficiency:** This centralized approach provides a more streamlined workflow, making it faster and easier to manage both your public-facing and internal traffic distribution.
* **Private Network Load Balancing:**  
   * **Secure Internal Application Access:** Create [**Private Load Balancers**](https://developers.cloudflare.com/load-balancing/private-network/) to distribute traffic to applications hosted within your private network, ensuring they are not exposed to the public Internet.  
   * **WARP & Magic WAN Integration:** Effortlessly direct internal traffic from users connected via Cloudflare WARP or through your Magic WAN infrastructure to the appropriate internal endpoint pools.  
   * **Enhanced Security for Internal Resources:** Combine reliable Load Balancing with Zero Trust access controls to ensure your internal services are both performant and only accessible by verified users.
![Private Load Balancers](https://developers.cloudflare.com/_astro/private-load-balancer.yti20m_p_q5zIk.webp) 

## 2025-05-06

  
**UDP and ICMP Monitor Support for Private Load Balancing Endpoints**   

Cloudflare Load Balancing now supports **UDP (Layer 4)** and **ICMP (Layer 3)** health monitors for **private endpoints**. This makes it simple to track the health and availability of internal services that don’t respond to HTTP, TCP, or other protocol probes.

#### What you can do:

* Set up **ICMP ping monitors** to check if your private endpoints are reachable.
* Use **UDP monitors** for lightweight health checks on non-TCP workloads, such as DNS, VoIP, or custom UDP-based services.
* Gain better visibility and uptime guarantees for services running behind **Private Network Load Balancing**, without requiring public IP addresses.

This enhancement is ideal for internal applications that rely on low-level protocols, especially when used in conjunction with [**Cloudflare Tunnel**](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/), [**WARP**](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/cloudflare-one-client/), and [**Magic WAN**](https://developers.cloudflare.com/cloudflare-wan/) to create a secure and observable private network.

Learn more about [Private Network Load Balancing](https://developers.cloudflare.com/load-balancing/private-network/) or view the full list of [supported health monitor protocols](https://developers.cloudflare.com/load-balancing/monitors/#supported-protocols).

## 2025-04-15

**Introducing Support for Orange-Clouded Origin Resolution**

Newly created Cloudflare Load Balancers will resolve orange-clouded origin addresses, provided the origins belong to the same account and zone as the Load Balancer. Existing Load Balancers will continue using the current resolution method. If ownership validation fails, the new system falls back to the existing behavior and defaults to a gray-clouded (DNS-only) lookup, typically resolving to anycast addresses.

## 2025-03-13

**Update to Load Balancing analytics**

Load Balancing request rates in analytics may decrease for some customers as an improvement is made to our infrastructure. This decrease in Load Balancing analytics does not indicate a decrease in HTTP requests received.

## 2025-02-20

**Zone name added to Load Balancing API responses**

Load Balancing API responses for Load Balancers now include a `zone_name` property, which provides the name of the zone in the response data.

## 2025-02-10

**Fix for Cloudflare Tunnel Consistency**

Fixes to improve the consistency of Cloudflare Tunnel handling within Cloudflare Load Balancers. These changes ensure more reliable and predictable routing, particularly when tunnels are involved.

## 2025-01-24

**Update to Cloudflare Tunnel Steering**

Introduced changes to the resolution of proxied domains that are backed by Cloudflare Tunnels on the same zone. These changes correct how orange-clouded records are steered to Cloudflare Tunnels via Cloudflare Load Balancers.

## 2025-01-16

**Update to Pool Health Monitoring**

We made changes to how we resolve and monitor proxied origins to assess pool health. Our analysis indicates no impact to customer configurations or operations. Contact customer support if you notice any unexpected behavior.

## 2024-12-20

**Load Balancing with the China Network**

You can now enable load balancers to be deployed to the [China Network](https://developers.cloudflare.com/china-network/). Refer to the [documentation](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-china/) for more details.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/changelog/","name":"Changelog"}}]}
```

---

---
title: Limitations
description: Load Balancing limitations and quotas.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Limitations

| Name              | Non-Enterprise           | Enterprise               |
| ----------------- | ------------------------ | ------------------------ |
| Load balancers    | 20                       | custom                   |
| Monitor intervals | 15s (min), 3600s (max)   | 10s (min), 3600s (max)   |
| Monitors          | 1.5x the number of pools | 1.5x the number of pools |
| Endpoints         | 20                       | custom                   |
| Pools             | 20                       | custom                   |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/reference/limitations/","name":"Limitations"}}]}
```

---

---
title: Analytics
description: Use load balancing analytics to evaluate traffic flow, assess the health of endpoints, and review health changes over time.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Analytics

Using load balancing analytics, you can:

* Evaluate traffic flow.
* Assess the health status of endpoints in your pools.
* Review changes in pools and pool health over time.

Note

Load balancing analytics are only available to customers on paid plans (Pro, Business, and Enterprise).

## Dashboard Analytics

### Overview metrics

To view **Overview** metrics for your load balancer, go to **Traffic** \> **Load Balancing Analytics**.

These metrics show the number of requests routed to specific pools within a load balancer, helping you:

* Evaluate the effects of adding or removing a pool.
* Decide when to create new pools.
* Plan for peak traffic demands and future infrastructure needs.

Add additional filters for specific pools, times, regions, and endpoints.

Note

Load balancing **requests** are the number of uncached requests made by your load balancer. By default, Cloudflare caches resolved IP addresses for up to five seconds.

### Latency

**Latency** metrics show an interactive map, helping you identify regions with **Unhealthy** or **Slow** pools.

To view latency information for your load balancer, go to **Traffic** \> **Load Balancing Analytics** \> **Latency**.

### Logs

**Logs** provide a history of all endpoint status changes and how they affect your load balancing pools. Load Balancing only logs events that represent a status change for an endpoint, from healthy to unhealthy or vice versa.

When a Monitor Group is attached to a pool, each logged health event includes the `monitors` field. This field lists the individual monitors within the group and their results, making it easier to see which monitor contributed to a status change.

Example event (truncated):

```

{

  "id": <id>,

  "timestamp": "2025-09-22 19:22:00",

  "pool": {

    "id": "<id>",

    "name": "example-monitor-group-test-pool-us",

    "healthy": true,

    "changed": false,

    "minimum_origins": 1

  },

  "origins": [

    {

      "name": "origin-a",

      "ip": "192.0.2.10",

      "enabled": true,

      "healthy": true,

      "failure_reason": "No failures",

      "response_code": 200,

      "monitors": [

        {

          "id": "<id>",

          "healthy": true,

          "failure_reason": "No failures",

          "response_code": 200,

          "must_be_healthy": true,

          "monitoring_only": false

        },

        {

          "id": "<id>",

          "healthy": true,

          "failure_reason": "No failures",

          "response_code": 200,

          "must_be_healthy": true,

          "monitoring_only": false

        },

        {

          "id": "<id>",

          "healthy": false,

          "failure_reason": "HTTP timeout occurred",

          "must_be_healthy": false,

          "monitoring_only": true

        }

      ]

    },

    {

      "name": "origin-b",

      "ip": "198.51.100.25",

      "enabled": true,

      "healthy": false,

      "failure_reason": "TCP connection failed",

      "changed": true,

      "monitors": [

        {

          "id": "<id>",

          "healthy": false,

          "failure_reason": "TCP connection failed",

          "must_be_healthy": true,

          "monitoring_only": false

        },

        {

          "id": "<id>",

          "healthy": true,

          "failure_reason": "No failures",

          "response_code": 200,

          "must_be_healthy": true,

          "monitoring_only": false

        },

        {

          "id": "<id>",

          "healthy": false,

          "failure_reason": "HTTP timeout occurred",

          "must_be_healthy": false,

          "monitoring_only": true

        }

      ]

    }

  ]

}


```

In this example:

* Each origin includes a `monitors` array listing all monitors within the attached group.
* Fields such as `must_be_healthy` `and monitoring_only` indicate each monitor's role in determining the origin's overall health.
* The `healthy` and `failure_reason` fields show which individual monitor checks succeeded or failed.

To access logs in the dashboard, go to **Traffic** \> **Load Balancing Analytics**.

## GraphQL Analytics

For more flexibility, get load balancing metrics directly from the [GraphQL Analytics API](https://developers.cloudflare.com/analytics/graphql-api/).

Get started with a sample query:

Requests per pool

This query shows the number of requests each pool receives from each location in Cloudflare's global network.

Query

```

query RequestsPerPool($zoneTag: string, $start: Time, $end: Time) {

  viewer {

    zones(filter: { zoneTag: $zoneTag }) {

      loadBalancingRequestsAdaptiveGroups(

        limit: 100

        filter: {

          datetime_geq: $start

          datetime_leq: $end

          lbName: "lb.example.com"

        }

        orderBy: [datetimeFifteenMinutes_DESC]

      ) {

        count

        dimensions {

          datetimeFifteenMinutes

          coloCode

          selectedPoolName

        }

      }

    }

  }

}


```

[Run in GraphQL API Explorer](https://graphql.cloudflare.com/explorer?query=I4VwpgTgngBASmUYDOAXZAFSGD2OA2AFACQBeOAdmACoCGA5gFwxoQCWF9ANDMWrRFTNqbALZgexMBQAmwsWACUMAN4AoGDABubMAHdIqjZpjkqyQgDM2+VJGYrTlGg2ZlndejAC+y9SZN8HFoZACFafFoKAGMOegQkNGQAQRlaAAdUNi0wAHEIHBB0i2MAzXwxNiEYAEYABjrSsutbeyMysrS7LPEAfXpEN35BJo6usB6wXvxB3mkZUbL8ACMAOVpxZgAiFYA6MAAPDfSZ3eicUS3FzW9rmBwIGUhQqGYAbXHJgDE2SztpACyHBAdmQvQAIgBRADKAGEALqLPx3c4gCioO4yBQUZBsSjIdodEyfBQ-P5gQHA0F3TTnIKwnBPGksMAzaJ2GS4AjrcR3W4dfkmQW3bxAA&variables=N4IgXg9gdgpgKgQwOYgFwgFoHkByBRAfQEkAREAGhAGcAXBAJxrRACYAGFgNgFo2eBGFnH4BWVPzbiA7BgogYUACbN2XXgKEt+4yfxkgAvkA)

Response (truncated)

```

{

    "data": {

        "viewer": {

            "zones": [

                {

                    "loadBalancingRequestsAdaptiveGroups": [

                        {

                            "count": 4,

                            "dimensions": {

                                "coloCode": "IAD",

                                "datetimeFifteenMinutes": "2021-06-26T00:45:00Z",

                                "selectedPoolName": "us-east"

                            }

                        },

                        ...

                    ]

                }

            ]

        }

    }

}


```

Requests per data center

This query shows the weighted, round-trip time (RTT) measurement (`avgRttMs`) for monitor requests from a specific data center (for example, Singapore or `SIN`) to each pool in a specific load balancer.

Warning

Note that `avgRttMs` refers to the round-trip time that is measured by the monitors and used in steering decisions. `avgRttMs` is different from the raw RTT for individual requests that reach the Cloudflare network.

Query

```

query RequestsPerDataCenter($zoneTag: string, $start: Time, $end: Time) {

  viewer {

    zones(filter: { zoneTag: $zoneTag }) {

      loadBalancingRequestsAdaptive(

        limit: 100

        filter: {

          datetime_geq: $start

          datetime_leq: $end

          lbName: "lb.example.com"

          coloCode: "SIN"

        }

        orderBy: [datetime_DESC]

      ) {

        selectedPoolName

        pools {

          poolName

          healthy

          healthCheckEnabled

          avgRttMs

        }

      }

    }

  }

}


```

[Run in GraphQL API Explorer](https://graphql.cloudflare.com/explorer?query=I4VwpgTgngBASmUYDOAXZAFSARAhq3AYTADtVIAKAEgC8B7EsAFVwHMAuGNCASxNYA0MKmlwRUnJjwC2YIVVIATSTLABKGAG8AUDBgA3HmADukLbr0x6jZBQBmPADbkInTVYbM2nWp5asYAF8NHUtLRzpcRQAhXEdcEgBjPlYEJDRkAEFFXAAHVB59MAoLML1HGR4JGABGAAY60rKHZ0g3JrKYHPIC2QB9VkQfUXEOsu6wXrA+xyHhJTGwxwAjADlcWU4AIhWAOjAADw3c2d3EumktxctziMI6RTBtgGUASVWrzr1A67oIR4g0SgnAA2hMpn1sABRZ6EAC6YxC12QYFmiXIigwdDojnWsmuuWxjmQ5i+lkJOLxYGuegAFmA4qhaVAaTB6YzaYR6YkANZQki4ZazRSs3D6VKoVAAWWQ1x+nXllkVP0CQA&variables=N4IgXg9gdgpgKgQwOYgFwgFoHkByBRAfQEkAREAGhAGcAXBAJxrRACYAGFgNgFo2eBGFnH4BWVPzbiA7BgogYUACbN2XXgKEt+4yfxkgAvkA)

Response (truncated)

```

{

    "data": {

        "viewer": {

            "zones": [

                {

                    "loadBalancingRequestsAdaptive": [

                        {

                            "pools": [

                                {

                                    "avgRttMs": 67,

                                    "healthCheckEnabled": 1,

                                    "healthy": 1,

                                    "poolName": "asia-ne"

                                },

                                {

                                    "avgRttMs": 156,

                                    "healthCheckEnabled": 1,

                                    "healthy": 1,

                                    "poolName": "us-east_and_asia-ne"

                                },

                                {

                                    "avgRttMs": 237,

                                    "healthCheckEnabled": 1,

                                    "healthy": 1,

                                    "poolName": "us-east"

                                },

                            ],

                            "selectedPoolName": "asia-ne"

                        },

                    ...

                    ]

                }

            ]

        }

    }

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/reference/load-balancing-analytics/","name":"Analytics"}}]}
```

---

---
title: Health monitor notifications
description: Migrate health monitor notifications.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Health monitor notifications

Cloudflare is migrating the notifications used by load balancing [health monitors](https://developers.cloudflare.com/load-balancing/monitors/) to use Cloudflare's centralized [Notifications Service](https://developers.cloudflare.com/notifications/).

## What is changing and why?

Cloudflare’s account-level [Notifications Service](https://developers.cloudflare.com/notifications/) is now the centralized location for most Cloudflare services. This change promotes consistency and streamlined administration, as well as gives you more options for notification delivery such as configuring webhooks or associating multiple pools with the same notification. These new notifications will also be managed at the account level instead of the zone level.

We strongly encourage all customers to migrate existing Health Monitor notifications to Cloudflare’s centralized Notifications Service to avoid lapses in alerts.

## Migration guide

You should use this guide to migrate over **all** your existing health monitor notifications.

### Step 1 - Find existing notifications

First you should determine which pools are using notifications. It's often easier if you use the Cloudflare API to list all your pools and look for the `notification_email` parameter.

With code

Use the [Cloudflare API](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/list/) to list all your pools and then look for whether each pool has a value for the `notification_email` parameter.

Request

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/load_balancers/pools" \

--header "Authorization: Bearer <API_TOKEN>" \

| jq '[.result[] | select(.notification_email != "") | {name, notification_email}]'


```

Response

```

[

    {

        "name": "pool-1",

        "notification_email": "user@example.com"

    },

    {

        "name": "pool-2",

        "notification_email": "user@example.com"

    },

    {

        "name": "pool-3",

        "notification_email": "user@example.com"

    },

    {

        "name": "pool-4",

        "notification_email": "user@example.com"

    }

]


```

No code

To find pools with existing notifications in the dashboard:

1. Log into the [Cloudflare dashboard ↗](https://dash.cloudflare.com) and select your account and domain.
2. Go to **Load Balancing**.
3. Select the **Pools** tab.
4. On a pool, select **Edit**.
5. For **Health Check Notifications**, check the value is toggled to **On** and an email address is present in the **Notification email address** field.

### Step 2 - Create new notifications

In this step, you should create new notifications to replace all of your existing legacy notifications.

With code

If using the Cloudflare API, [re-create all your existing notifications](https://developers.cloudflare.com/api/resources/alerting/subresources/policies/methods/create/) with the following parameters specified:

```

"alert_type": "load_balancing_health_alert",

"filters": {

    "pool_id": <<ARRAY_OF_INCLUDED_POOL_IDS>>,

    "new_health": <<ARRAY_OF_STATUS_TRIGGERS>> ["Unhealthy", "Healthy"],

    "event_source": <<ARRAY_OF_OBJECTS_WATCHED>> ["pool", "origin"]

}


```

No code

On the pool you located in [Step 1](#step-1---find-existing-notifications), look for **Pool Notifications**. Click **Create a Health Alert** to start [creating a notification](https://developers.cloudflare.com/notifications/get-started/#create-a-notification).

### Step 3 - Remove deprecated notifications

As the final step in the migration process, you need to remove all emails from your legacy notifications to ensure that you no longer receive deprecation emails moving forward.

Though you can perform these steps in the dashboard, Cloudflare recommends you use our new API endpoint for added convenience.

With code

If using the Cloudflare API, we recently added a [PATCH](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/bulk%5Fedit/) endpoint so you can easily remove email notifications from multiple pools at the same time.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Load Balancing: Monitors and Pools Write`

Patch Pools

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/load_balancers/pools" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "notification_email": ""

  }'


```

This API call supports the standard pagination query parameters, either `limit/offset` or `per_page/page`, so by default it only updates the first 25 pools listed. To make sure you update all your pools, you may want to adjust your API call so it loops through various pages or includes a larger number of pools with each request.

If needed, you can remove legacy notifications by using the dashboard.

No code

Once you created your new notification in [Step 2](#step-2---create-new-notifications), you will return to the pool you were editing previously. To disable the deprecated notifications, you must remove all notification email addresses from the field.

If you do not complete this step (removing all notification emails from all pools), your migration will not be considered complete and you will continue to receive additional emails about this deprecation.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/reference/migration-guides/","name":"Migration guides"}},{"@type":"ListItem","position":5,"item":{"@id":"/load-balancing/reference/migration-guides/health-monitor-notifications/","name":"Health monitor notifications"}}]}
```

---

---
title: Migrate to new GraphQL nodes
description: Migrate to new GraphQL analytics nodes.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Migrate to new GraphQL nodes

After 30 September 2021, Cloudflare will make the following changes to the Load Balancing GraphQL schema:

* Deprecate nodes:  
   * `loadBalancingRequestsGroups` will be deprecated for `loadBalancingRequestsAdaptiveGroups`  
   * `loadBalancingRequests` will be deprecated for `loadBalancingRequestsAdaptive`
* Deprecate the `date` field (replace it with the existing `datetime` field)
* Add the `sampleInterval` field

## Example query

The following example:

* Replaces `loadBalancingRequestsGroups` with `loadBalancingRequestsAdaptiveGroups`
* Replaces `date` with `datetime`
* Uses the new `sampleInterval` field

```

query {

  viewer {

    zones(filter: { zoneTag: "your Zone ID" }) {

      loadBalancingRequestsAdaptiveGroups(

        filter: {

          datetime_gt: "2021-06-12T04:00:00Z",

          datetime_lt: "2021-06-13T06:00:00Z"

        }

      ) {

        dimensions {

          datetime

          coloCode

          ...

        }

        avg {

          sampleInterval

        }

      }

    }

  }

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/reference/migration-guides/","name":"Migration guides"}},{"@type":"ListItem","position":5,"item":{"@id":"/load-balancing/reference/migration-guides/load-balancing-graphql-nodes/","name":"Migrate to new GraphQL nodes"}}]}
```

---

---
title: Regions API
description: Map geographic regions to pools using the API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Regions API

Cloudflare’s Load Balancing Regions API has several uses:

* Identify which countries/areas (states/provinces in the case of the U.S. and Canada) are part of a specific Cloudflare Load Balancer region.
* Identify the Cloudflare Load Balancer region for a particular country/area (states/provinces in the case of the U.S. and Canada).

The Region API uses 2-letter [ISO-3166-1 alpha-2 codes ↗](https://www.iso.org/iso-3166-country-codes.html) for countries/areas and, in the case of the U.S. and Canada, ISO-3166-2 subdivision codes for states/provinces. Only the U.S. and Canada are provided with these subdivisions.

There are two main optional parameters for the Region API:

* country\_code is a string containing a two-letter alpha-2 country code per ISO 3166-1\. For example: /load\_balancers/regions?country\_code=US
* subdivision\_code is a string containing a two-letter subdivision code for the U.S. and Canada per ISO 3166-2\. For example: /load\_balancers/regions?subdivision\_code=CA

For additional details and examples on using the Region Mapping API, see [Cloudflare’s API documentation](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/regions/methods/list/).

## List of Load Balancer regions

| Region code | Region name            |
| ----------- | ---------------------- |
| EEU         | Eastern Europe         |
| ENAM        | Eastern North America  |
| ME          | Middle East            |
| NAF         | Northern Africa        |
| NEAS        | Northeast Asia         |
| NSAM        | Northern South America |
| OC          | Oceania                |
| SAF         | Southern Africa        |
| SAS         | Southern Asia          |
| SEAS        | Southeast Asia         |
| SSAM        | Southern South America |
| WEU         | Western Europe         |
| WNAM        | Western North America  |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/reference/region-mapping-api/","name":"Regions API"}}]}
```

---

---
title: Common error codes
description: Common Load Balancing error codes and resolutions.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Common error codes

The Cloudflare Load Balancing API adds global health to each pool and endpoint. It also gives you a view into what our network sees at a wider level. Cloudflare uses a quorum system to determine pool and endpoint health status. The quorum is taken from PoPs responsible for running health monitor requests in a region, and the majority result is used.

When troubleshooting failures, use the Cloudflare API for programmatic access to Cloudflare Load Balancing. The Health Monitor Events and Load Balancer Monitors routes are excellent tools for accessing load balancing event logs and reconfiguring Cloudflare monitors.

You can get a per-data center breakdown of the health of your endpoints from the Cloudflare API from the List Health Monitor Events command:

```

GET user/load_balancing_analytics/events


```

If a health monitor request fails, the breakdown will include the reason.

Common troubleshooting causes and solutions are listed below.

---

## TCP connection failed

### Cause

Our health monitor requests failed to establish a TCP connection to your endpoint.

### Solution

This typically occurs when there is a network failure between Cloudflare and your endpoint, and/or a firewall refused to allow our connection. Ensure your network and firewall configurations are not interfering with load balancing traffic.

---

## HTTP timeout occurred

### Cause

The endpoint failed to return an HTTP response within the timeout configured. This happens if you have the timeout set to a low number — 1 or 2 seconds, for instance.

### Solution

We recommend increasing the HTTP response timeout to allow the endpoint to respond.

---

## Response code mismatch error

### Cause

Cloudflare receives an HTTP status code that does not match the values defined in the `expected_codes` property of your Cloudflare monitor configuration.

### Solution

Response codes must match the `expected_codes`. Use the List Monitors API command to confirm the values are correct.

### Alternate cause

You may also see this issue if you have a monitor configured to use HTTP connections and your endpoint is redirecting to HTTPS. In this case, the response code will often be 301, 302, or 303.

### Solution

Either change your Cloudflare monitor configuration to use HTTPS, or set the value of `follow_redirect` to `true` so that we can resolve the correct status code.

---

## Response body mismatch error

### Cause

The response body returns from your endpoint and does not include the (case-insensitive) value of `expected_body` configured in your monitor.

Note that we only read the first 10 KB of the response. If you return a larger response, and the expected\_body is not in the first 10 KB, the health monitor request will fail.

### Solution

Ensure the expected\_body is in the first 10 KB of the response body.

---

## TLS untrusted certificate error

### Cause

The certificate is not trusted by a public Certificate Authority (CA).

### Solution

If you're using a self-signed certificate, we recommend either using a publicly trusted certificate or setting the `allow_insecure` property on your monitor to `true`.

---

## TLS name mismatch error

### Cause

Our health monitor (client) was not able to match a name on the server certificate to the hostname of the request.

### Solution

Use the List Monitors command to confirm that the `header` value set in the Cloudflare monitor is correct and the Update Monitors command to make any necessary changes.

---

## TLS protocol error

### Cause

This error can occur if you’re using an older version of TLS or your endpoint is not configured for HTTPS.

### Solution

Ensure that your endpoint supports TLS 1.0 or greater and is configured for HTTPS.

---

## TLS unrecognized name error

### Cause

The server did not recognize the name provided by the client. When a host header is set, we set this as the ServerName in the initial TLS handshake. If not set, we will not provide a ServerName, which can cause this error.

### Solution

Set the host header in your monitor object.

---

## No route to host error

### Cause

The IP address cannot be reached from our network. Common causes are ISP or hosting provider network issues (e.g. BGP level), or that the IP does not exist.

### Solution

Make sure IP is accurate, and if it is check if there is an ISP or hosting provider network issue.

---

## Exceeded quota error

### Cause

You will receive this error if you attempt to create more objects (monitors, pools, or endpoints) than are included in your plan.

If using the dashboard, you will not be able to create additional objects.

If you're using the **Cloudflare API**, you will receive an error message.

### Solution

* Enterprise customers who need to create more objects (load balancers, pools, endpoints, or monitors) should reach out to their account team to discuss this issue.
* Self-service customers can upgrade their Load Balancing subscription with more endpoints to increase load balancing capacity.

---

## TCP Timeout

### Cause

Data transmission was not acknowledged and retransmit of data did not succeed.

### Solution

Confirm whether the SYN-ACK for the handshake takes place at your endpoint and [contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/).

---

## TLS Handshake Failure

### Cause

Indicates that the browser's connection to the web server is not secure.

### Solution

Change wifi networks, connect to a wired network, or verify the network connection is stable.

---

## Network Unreachable

### Cause

Cloudflare cannot connect to the endpoint due to network unavailability. This is usually caused by a network issue or incorrect IP.

### Solution

Check either the IP entered for the endpoint in Cloudflare's Load Balancer configuration or the IP returned via DNS for the endpoint hostname.

---

## HTTP Invalid Response

### Cause

Usually caused by an HTTP 502 error or bad gateway.

### Solution

Ensure the endpoint responds to requests and that no applications have crashed or are under high load.

---

## DNS Unknown Host

### Cause

The endpoint hostname does not exist.

### Solution

Confirm the endpoint resolves to an IP address.

---

## Connection Reset by Peer

### Cause

A network error occurred while the client received data from the endpoint.

### Solution

Confirm whether the endpoint is experiencing a high amount of traffic or an error.

---

## Monitor Config Error

### Cause

There was a configuration error in the monitor and no checks are run against the pool endpoints.

### Solution

Review your monitor configuration to ensure it matches an expected request to your endpoint.

---

## DNS Internal

### Cause

The endpoint's hostname resolves to an internal or orange-clouded IP address. No checks are run against the pool endpoints.

### Solution

Cloudflare does not allow use of an endpoint hostname that is proxied by Cloudflare.

---

## Load Balancing Not Enabled

### Cause

Load Balancing is not enabled for your account or zone.

### Solution

For Enterprise customers, reach out to your Cloudflare Account Team. Free, Pro, and Business customers should [Enable Load Balancing](https://developers.cloudflare.com/load-balancing/get-started/enable-load-balancing/).

---

## Validation failed error

### Cause

You will receive an error if you try to set the host header value while configuring a load balancer endpoint.

### Solution

Cloudflare now restricts configured [endpoint host headers](https://developers.cloudflare.com/load-balancing/additional-options/override-http-host-headers/) to fully qualified domain names (FQDNs) that are immediate subdomains of a zone associated with the account. For example, this host header would be the same zone as the load balancer itself, but pools may be used across multiple Load balancers.

---

## Object referenced by other objects

### Cause

You will receive this error when you attempt to delete a pool that is referenced by a load balancer [geo steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/geo-steering/) region.

### Solution

Remove the pool from the load balancer's geo steering configuration. If your load balancer no longer uses geo steering, you will need to [re-enable geo steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/geo-steering/) and then remove the pool.

---

## Other Failure

### Cause

If the failure cannot be classified as any other type of failure mentioned above.

### Solution

[Contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/troubleshooting/common-error-codes/","name":"Common error codes"}}]}
```

---

---
title: FAQs
description: Answers to common Load Balancing questions.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# FAQs

## Overview

For more detailed information about Load Balancing — including how-to guides, tutorials, and other reference information — check out our [product documentation](https://developers.cloudflare.com/load-balancing/).

Note

Are you trying to turn on Load Balancing? [Enable Load Balancing ↗](https://dash.cloudflare.com/?to=/:account/:zone/traffic/load-balancing).

---

## Why is my origin receiving so many health monitor requests?

This issue may be caused by a combination of two issues.

### Multiple Health Monitor Regions

When you [attach a monitor to a pool](https://developers.cloudflare.com/load-balancing/monitors/create-monitor/#create-a-monitor), you can specify the **Health Monitor Regions** that Cloudflare uses to monitor your endpoint health.

If you select multiple regions or choose **All Data Centers (Enterprise Only)**, you may [dramatically increase traffic](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/#how-an-endpoint-becomes-unhealthy) to that pool and its associated endpoints. Each region sends individual health monitor requests from 3 data centers. Using **All Data Centers** sends individual health monitor requests from all existing Cloudflare data centers (and that number of data centers is growing all the time).

To reduce traffic, reduce the number of selected regions or choose an option besides **All Data Centers**.

### Low intervals for health monitor requests

If you have a low interval for your health monitor requests, you may increase the traffic sent to your endpoints.

---

## Why is my endpoint or pool considered unhealthy?

To learn more about how endpoints and pools become unhealthy, refer to [Endpoint and pool health](https://developers.cloudflare.com/load-balancing/understand-basics/health-details).

If you know that your endpoint is healthy but load balancing is reporting it as unhealthy, check the following settings on the [monitor](https://developers.cloudflare.com/load-balancing/monitors):

* Perform a `curl` request against the configured endpoint. Make sure the response you are seeing matches your settings for the monitor.
* Ensure your firewall or web server does not block or rate limit [our health monitors](https://developers.cloudflare.com/fundamentals/reference/cloudflare-site-crawling/#specific-products) and accepts requests from [Cloudflare IP addresses](https://developers.cloudflare.com/fundamentals/concepts/cloudflare-ip-addresses/).
* If you are looking for a specific value in the **Response Body**, make sure that value is relatively static and within the first 10 KB of the HTML page.
* If your endpoint responds with a `301` or `302` status code, make sure **Follow Redirects** is selected.
* Try increasing the **Timeout** value.
* Review the **Host Header** for the health monitor.
* If you are using [Authenticated Origin Pulls (mTLS)](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/), [Argo Smart Routing](https://developers.cloudflare.com/argo-smart-routing/), [Bring your own CA (mTLS)](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/), [Dedicated CDN Egress IPs](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/), or require [HTTP/2 to Origin](https://developers.cloudflare.com/speed/optimization/protocol/http2-to-origin/), make sure that you entered a zone value for **Simulate Zone** corresponding to the zone with these features configured.

---

## Why does my load balancer route traffic to a secondary pool when the primary pool is still healthy?

You occasionally might see traffic routed away from a pool if a health monitor request fails from a specific data center (even if the endpoint is still healthy). That data center may direct a small number of requests to another pool that is considered healthy by that data center.

To learn more about how endpoints and pools become unhealthy, refer to [Endpoint and pool health](https://developers.cloudflare.com/load-balancing/understand-basics/health-details).

---

## What happens when a pool or endpoint becomes unhealthy?

When a pool or endpoint becomes unhealthy, traffic may be rerouted to other healthy pools or endpoints based on your configuration. You might experience this behavior when using:

1 - Pools with **All-Datacenters** monitoring and the monitor fails in a specific data center. In this case, all traffic will be steered away from impacted endpoints in that datacenter until the monitor succeeds again. These instances are reflected in LB request analytics as steering away from an unhealthy endpoint or pool.

2 - Pools with FQDN endpoint addresses and the recursive DNS lookup fails in a specific data center. In this case, only requests for which the DNS request fails will be steered away from impacted endpoints. This could be sporadic, especially if upstream authoritative resolvers occasionally time out or fail, when the local DNS cache TTL expires and a remote lookup is required in the hot path. This also appears in LB request analytics as steering away from an unhealthy endpoint, and the resolved endpoint IP will be missing from the request log.

To avoid these scenarios:

1 - Do not use **All-Datacenters** monitoring.

2 - Use IP addresses for endpoint configurations. If that is not feasible, use domains for which Cloudflare is authoritative (primary or secondary).

To learn more about how endpoints and pools become unhealthy, refer to [Endpoint and pool health](https://developers.cloudflare.com/load-balancing/understand-basics/health-details).

---

## What is the difference between Load Balancing and Health Checks?

[Cloudflare Load Balancing](https://developers.cloudflare.com/load-balancing/) helps monitor endpoints health and — based on that and other information — route incoming requests accordingly. Individual endpoints have monitors attached, which issue monitor requests at regular intervals.

[Cloudflare Health Checks](https://developers.cloudflare.com/health-checks/) are identical to monitors within a load balancer, but only meant for probing server health (and not distributing traffic).

---

## Why do I see different numbers of requests in Load Balancing Analytics?

You may see different numbers of requests when reviewing [Load Balancing Analytics](https://developers.cloudflare.com/load-balancing/reference/load-balancing-analytics/), especially when compared to other Cloudflare dashboards (Caching, etc.).

Load balancing **requests** are the number of uncached requests made by your load balancer. By default, Cloudflare caches resolved IP addresses for up to five seconds. This built-in caching is often the cause of an discrepancies.

---

## I'm seeing a specific error code for my load balancer or monitor.

For a list of specific error codes and next steps, refer to [Load Balancing Troubleshooting](https://developers.cloudflare.com/load-balancing/troubleshooting).

---

## Related resources

* [Endpoint and pool health](https://developers.cloudflare.com/load-balancing/understand-basics/health-details)
* [Monitors](https://developers.cloudflare.com/load-balancing/monitors)
* [Load Balancing Analytics](https://developers.cloudflare.com/load-balancing/reference/load-balancing-analytics/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/troubleshooting/load-balancing-faq/","name":"FAQs"}}]}
```

---

---
title: Adaptive routing
description: Route traffic based on origin health and latency.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Adaptive routing

Adaptive routing controls features that modify the routing of requests to pools and endpoints in response to dynamic conditions, such as during the interval between active health monitoring requests. 

Zero-downtime failover will trigger a single retry only if there is another healthy endpoint in the pool and a [521, 522, 523, 525 or 526 error code](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-521/) is occurring. No other error codes will trigger a zero-downtime failover operation.

## Failover across pools

When there are no healthy endpoints in the same pool, failover across pools extend the zero-downtime failover of requests to healthy endpoints in alternate pools according to the failover order defined by traffic and endpoint steering.

### Enable failover across pools

1. In the Cloudflare dashboard, go to the **Load Balancing** page.  
[ Go to **Load Balancing** ](https://dash.cloudflare.com/?to=/:account/load-balancing)
2. Navigate to your Load Balancers and select **Edit**.
3. From **Adaptive Routing**, enable **Failover across pools**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/understand-basics/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/understand-basics/adaptive-routing/","name":"Adaptive routing"}}]}
```

---

---
title: How endpoints and pools become unhealthy
description: How endpoints and pools become unhealthy.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# How endpoints and pools become unhealthy

When we talk about dynamic load balancing, that means your load balancer only directs requests to endpoints that can handle the traffic.

But how does your load balancer _know_ which endpoints can handle the traffic? We determine that through a system of monitors, health monitors, and pools.

---

## Dynamic load balancing

Dynamic load balancing happens through a combination of [pools](https://developers.cloudflare.com/load-balancing/pools/), [monitors](https://developers.cloudflare.com/load-balancing/monitors/), and health checks.

    flowchart RL
      accTitle: Load balancing monitor flow
      accDescr: Monitors issue health monitor requests, which validate the current status of servers within each pool.
      Monitor -- Health Monitor ----> Endpoint2
      Endpoint2 -- Response ----> Monitor
      subgraph Pool
      Endpoint1((Endpoint 1))
      Endpoint2((Endpoint 2))
      end

---

## How an endpoint becomes unhealthy

Health checks are requests issued by a monitor at regular interval and — depending on the monitor settings — return a **pass** or **fail** value to make sure an endpoint is still able to receive traffic.

Each health monitor request is trying to answer two questions:

1. **Is the endpoint offline?**: Does the endpoint respond to the health monitor request at all? If so, does it respond quickly enough (as specified in the monitor's **Timeout** field)?
2. **Is the endpoint working as expected?**: Does the endpoint respond with the expected HTTP response codes? Does it include specific information in the response body?

If the answer to either of these questions is "No", then the endpoint fails the health monitor request.

For each option selected in a pool's **Health Monitor Regions**, Cloudflare sends health monitor requests from three separate data centers in that region.

![Health monitor requests come from three data centers within each selected region.](https://developers.cloudflare.com/_astro/health-check-component.wo0_f7k-_Z1C61Ll.webp) 

If the majority of data centers for that region pass the health monitor requests, that region is considered healthy. If the majority of regions is healthy, then the endpoint itself will be considered healthy.

Note

If **Health Monitor Regions** for a pool is set to **All Data Centers (Enterprise)**, pool health is determined by a majority of data centers.

Load balancing analytics and logs will only show global health changes.

For greater accuracy and consistency when changing endpoint health status, you can also set the `consecutive_up` and `consecutive_down` parameters via the [Create Monitor API endpoint](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/monitors/methods/create/). To change from healthy to unhealthy, an endpoint will have to be marked healthy a consecutive number of times (specified by `consecutive_down`). The same applies — from unhealthy to healthy — for `consecutive_up`.

---

## How a pool becomes unhealthy

When an [individual endpoint becomes unhealthy](#how-an-endpoint-becomes-unhealthy), that may affect the health status of any associated pools (visible in the dashboard):

* **Healthy**: All endpoints are healthy.
* **Degraded**: At least one endpoint is unhealthy, but the pool is still considered healthy and could be receiving traffic.
* **Critical**: The pool has fallen below the number of available endpoints specified in its **Health Threshold** and will not receive traffic from your load balancer (unless other pools are also unhealthy and this pool is marked as the [**Fallback Pool**](#fallback-pools)).
* **Health unknown**: There are either no monitors attached to pool endpoints or the monitors have not yet determined endpoint health.
* **No health**: Reserved for your load balancer's [**Fallback Pool**](#fallback-pools).

Note

1. When no monitor is attached to a pool, the health status is not considered during steering.
2. Origins are considered down when monitoring is enabled, but the health status is still unknown.
3. If there are no monitors, a fallback pool is still required, but it will only be used if all the default pools have origins with FQDN addresses that cannot be resolved.

### Traffic distribution

When a pool reaches **Critical** health, your load balancer will begin diverting traffic according to its [Traffic steering policy](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/):

* **Off**:  
   * If the active pool becomes unhealthy, traffic goes to the next pool in order.  
   * If an inactive pool becomes unhealthy, traffic continues to go to the active pool (but would skip over the unhealthy pool in the failover order).
* **All other methods**: Traffic is distributed across all remaining pools according to the traffic steering policy.

### Fallback pools

This pool is meant to be the pool of last resort, meaning that its health is not taken into account when directing traffic.

Fallback pools are important because traffic still might be coming to your load balancer even when all the pools are unreachable (disabled or unhealthy). Your load balancer needs somewhere to route this traffic, so it will send it to the fallback pool.

---

## How a load balancer becomes unhealthy

When one or more pools become unhealthy, your load balancer might also show a different status in the dashboard:

* **Healthy**: All pools are healthy.
* **Degraded**: At least one pool is unhealthy, but traffic is not yet going to the [Fallback Pool](#fallback-pools).
* **Critical**: All pools are unhealthy and traffic is going to the [Fallback Pool](#fallback-pools).

If a load balancer reaches **Critical** health and the pool serving as your fallback pool is also disabled:

* If Cloudflare proxies your hostname, you will see a 530 HTTP/1016 Origin DNS failure.
* If Cloudflare does not proxy your hostname, you will see the SOA record.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/understand-basics/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/understand-basics/health-details/","name":"How endpoints and pools become unhealthy"}}]}
```

---

---
title: Load Balancing components
description: Load balancers, pools, monitors, and how they work together.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Load Balancing components

This page provides a simplified overview of the three main components of the Cloudflare Load Balancing solution and how they relate to one another.

## Load balancers

For a hostname (`blog.example.com`) to resolve, the Domain Name System (DNS) must return an IP address, where the website or application is hosted (origin).

When you set up a public load balancer, Cloudflare automatically creates an [LB DNS record](https://developers.cloudflare.com/load-balancing/load-balancers/dns-records/) for the specified hostname. This means that, according to a [priority order](https://developers.cloudflare.com/load-balancing/load-balancers/dns-records/#priority-order), instead of simply returning an IP address, the logic you introduced using the Cloudflare Load Balancing solution will be considered.

Note that you can use the root domain as a Load Balancer hostname. When doing so, make sure you enter the hostname without including the auto-generated dot that typically precedes your zone's name.

Note

Private load balancers are not automatically associated with a hostname. Private load balancers are created with either a CGNAT IP address or a custom RFC-1918 IP address.

    flowchart LR
      accTitle: Load balancing flow
      accDescr: Load balancing involves a load balancer, pools, endpoints, monitors, and health monitors.
      B[Request 1] --> A
      C[Request 2] --> A
      D[Request 3] --> A
      A[Load balancer] -- Request 1 --> P1
      A -- Request 2 --> P2
      A -- Request 3 --> P3
      subgraph P1 [Pool 1]
      Endpoint1((Endpoint 1))
      Endpoint2((Endpoint 2))
      end
      subgraph P2 [Pool 2]
      Endpoint3((Endpoint 3))
      Endpoint4((Endpoint 4))
      end
      subgraph P3 [Pool 3]
      Endpoint5((Endpoint 5))
      Endpoint6((Endpoint 6))
      end

## Pools

Within Cloudflare, pools represent your endpoints and how they are organized. As such, a pool can be a group of several endpoints, or you could also have only one endpoint per pool — it depends on what best suits your use case.

For example, if you are only using Cloudflare to globally distribute traffic across regions ([global traffic steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/)), each pool could represent one region and, within each region, you could have one endpoint that represents the entry point to your data center.

Cloudflare [Private Network Load Balancing](https://developers.cloudflare.com/load-balancing/private-network/) solution and [endpoint steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/) capabilities enable you to also load balance traffic between your servers within a data center. In this use case, each pool would represent a data center and contain several endpoints that represent your servers.

Smart Tiered Cache interaction

While Smart Tiered Cache selects one Upper Tier per origin, when using Load Balancing, Smart Tiered Cache will select the single best Upper Tier for the entire Load Balancing Pool.

## Endpoints

Endpoints refer to any service or hardware that intercepts and processes incoming public or private traffic.

Examples of endpoints include origins, hostnames, private or public IP addresses, virtual IP addresses (VIPs), servers, and other dedicated hardware boxes.

## Monitors

Finally, monitors are the component you can use to guarantee only [healthy pools](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/) are considered for traffic distribution.

When you configure a monitor and attach it to endpoints, the monitor will issue health monitor requests to your endpoints at regular intervals. This process makes it possible for your load balancer to intelligently handle traffic, considering which endpoints are actually available.

    flowchart RL
      accTitle: Load balancing monitor flow
      accDescr: Monitors issue health monitor requests, which validate the current status of servers within each pool.
      Monitor -- Health Monitor ----> Endpoint2
      Endpoint2 -- Response ----> Monitor
      subgraph Pool
      Endpoint1((Endpoint 1))
      Endpoint2((Endpoint 2))
      end

Note

Health monitors associated with load balancers are different from [**Standalone health checks**](https://developers.cloudflare.com/health-checks/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/understand-basics/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/understand-basics/load-balancing-components/","name":"Load Balancing components"}}]}
```

---

---
title: Proxy status
description: Proxy status options for load balanced traffic.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Proxy status

You can load balance your traffic at different levels of the networking stack, such as:

* [Layer 7 (HTTP/HTTPS)](#layer-7-load-balancing) (most common)
* [DNS-only](#dns-only-load-balancing)
* [Layer 4 (TCP)](#layer-4-load-balancing)

---

## Layer 7 load balancing

Layer 7 load balancers direct traffic to specific endpoints based on information present in each HTTP/HTTPS request (HTTP headers, URI, cookies, type of data, etc.).

When a client visits your application, Cloudflare directs their request to a healthy endpoint (determined by your [traffic steering policy](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/) and [endpoint weights](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/#weights)).

Cloudflare performs layer 7 load balancing when traffic to your hostname is **proxied** through Cloudflare. In the **Load Balancing** dashboard, these load balancers are marked with an orange cloud.

![DNS-only load balancers are marked with an orange cloud](https://developers.cloudflare.com/_astro/proxied-load-balancer.BMq3VCyA_1BeaMW.webp) 

Note that if a [DNS-only (grey cloud)](https://developers.cloudflare.com/dns/proxy-status/) CNAME record points to a proxied load balancer, the IP returned for it would be endpoint IP and a HTTP request sent to it would not be proxied.

### Benefits

In comparison to DNS-only load balancing, layer 7 load balancing:

* Protects endpoints from DDoS attacks by hiding their IP addresses.
* Offers faster failover and more accurate routing, which can otherwise be affected by DNS caching.
* Integrates with other Cloudflare features such as caching, Workers, and the WAF.
* Reduces authoritative queries against Cloudflare, which can potentially save money for customers with usage-based billing.
* Supports customized [session affinity](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/) and [endpoint drain](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/#endpoint-drain).
* More accurately geo-locates traffic, using the data center associated with the user making the request instead of the data center associated with a user's recursive resolver.
* Supports private IP addresses with [Private Network Load Balancing](https://developers.cloudflare.com/load-balancing/private-network/).

---

## DNS-only load balancing

DNS-only load balancers route traffic by returning specific IP addresses in response to a client's DNS query.

When a client visits your application, Cloudflare provides the address for a healthy endpoint (determined by your [traffic steering policy](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/) and [endpoint-level steering policy](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/)). However, Cloudflare relies on DNS resolvers respecting the short TTL to re-query Cloudflare's DNS for an updated list of healthy addresses. If a client has a cached DNS response, they will go to their previous destination, potentially ignoring your load balancer.

Cloudflare performs DNS-only load balancing when traffic to your hostname is **not proxied** through Cloudflare. In the **Load Balancing** dashboard, these load balancers are marked with a gray cloud.

![DNS-only load balancers are marked with a gray cloud](https://developers.cloudflare.com/_astro/dns-only-load-balancer.DI9EgD6m_1nkQpb.webp) 

Note

Note that if a load balancer endpoint is a [proxied (orange-cloud)](https://developers.cloudflare.com/dns/proxy-status/) CNAME record on Cloudflare, the IP returned for it would be Cloudflare's and a HTTP request sent to it would be proxied accordingly.

### Benefits

If your load balancer is attached to a hostname used for an [MX or SRV record](https://developers.cloudflare.com/load-balancing/additional-options/additional-dns-records/) — and not an `A`, `AAAA`, or `CNAME` record — its proxy mode should be **DNS-only**.

  
### Limitations

In comparison to proxied, layer 7 load balancing, DNS-only load balancing:

* Does not hide the IP addresses of your endpoints, leaving them vulnerable to DDoS attacks.
* Performs slower failover and less accurate routing, because it has to rely on DNS resolvers and cache settings.
* Cannot integrate with other Cloudflare features such as caching, Workers, and the WAF.
* Increases authoritative queries against Cloudflare, which can potentially cost more for customers with usage-based billing.
* Does not support [session affinity](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/). Alternatively, you can use [DNS persistence](https://developers.cloudflare.com/load-balancing/additional-options/dns-persistence/).
* Geo-locates traffic based on the data center associated with the ECS source address, if available. If not available, geo-locates based on a user's recursive resolver, which can sometimes cause issues with [latency-based steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/dynamic-steering/).
* Does not support [Private Network Load Balancing](https://developers.cloudflare.com/load-balancing/private-network/).

---

## Layer 4 load balancing

Layer 4 load balancers route traffic by forwarding traffic to certain ports or IP addresses.

Cloudflare currently only supports layer 4 load balancing as part of [Cloudflare Spectrum](https://developers.cloudflare.com/spectrum/about/load-balancer/).

Note

Since Spectrum operates at the TCP level, it does not have the information to support features like [session affinity](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/), [custom rules](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/), or caching.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/understand-basics/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/understand-basics/proxy-modes/","name":"Proxy status"}}]}
```

---

---
title: Session affinity
description: Route repeat visitors to the same origin server.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Session affinity

When you enable session affinity, your load balancer directs all requests from a particular end user to a specific endpoint. This continuity preserves information about the user session — such as items in their shopping cart — that might otherwise be lost if requests were spread out among multiple servers.

Session affinity can also help reduce network requests, leading to savings for customers with usage-based billing.

Note

Session Affinity is only supported by Public Load Balancers.

## Types

Session affinity specifies the type of session affinity the load balancer should use unless specified as `"none"` or `""` (default).

### By Cloudflare cookie only

On the first request to a proxied load balancer, a cookie is generated, encoding information of which endpoint the request will be forwarded to. Subsequent requests, by the same client to the same load balancer, will be sent to the endpoint the cookie encodes for the duration of the cookie and as long as the endpoint remains healthy. If the cookie has expired or the endpoint is unhealthy, a new endpoint is calculated and used.

#### How does it work?

Session affinity automatically directs requests from the same client to the same endpoint:

1. When a client makes its first request, Cloudflare sets a `__cflb` cookie on the client (to track the associated endpoint).
2. Subsequent requests by the same client are forwarded to that endpoint for the duration of the cookie and as long as the endpoint remains healthy.
3. If the cookie expires or the endpoint becomes unhealthy, Cloudflare sets a new cookie tracking the new failover endpoint.

    flowchart LR
      accTitle: Session affinity process
      accDescr: Session affinity directs requests from the same client to the same server.
     A[Client] --Request--> B{<code>__cflb</code> cookie set?}
     B -->|Yes| C[Route to previous endpoint]
     C --> O2
     B ---->|No| E[Follow normal routing]
     E --> O2
     E --Set <code>__cflb</code> cookie--> A
     subgraph P1 [Pool 1]
        O1[Endpoint 1]
        O2[Endpoint 2]
     end

  
All cookie-based sessions default to 23 hours unless you set a custom session _Time to live_ (TTL).

The session cookie is secure when [Always Use HTTPS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/) is enabled. Additionally, HttpOnly is always enabled for the cookie to prevent cross-site scripting attacks.

### By Cloudflare cookie and Client IP fallback

This behaves similar to `cookie` except the initial endpoint selection is stable and based on the client's IP address.

### By HTTP header

On the first request to a proxied load balancer, a session key based on the configured HTTP headers is generated. The session key encodes the request headers used for storing which endpoint the request will be forwarded to during the load balancer session state. Subsequent requests to the load balancer with the same headers will be sent to the same endpoint, for the duration of the session and as long as the endpoint remains healthy. If the session has been idle for the duration of session affinity TTL seconds or the endpoint is unhealthy, then a new endpoint is calculated and used.

Note

[Sticky Zero-Downtime Failover](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/#zero-downtime-failover) is not supported for session affinity by HTTP header.

#### Control how headers are used

By default, at least one of the HTTP headers that you configure for session affinity by HTTP header must be present on requests sent to your load balancer in order for header-based sessions to be created. If a client adds or removes HTTP headers on their requests and they have already established a session, a new session will be created based on the new HTTP headers found in subsequent requests as long as they are specified in your configuration.

If you would like to require all of your configured HTTP headers to be present on requests in order for sessions to be created, then set `session_affinity_attributes.require_all_headers` to `true` via the Cloudflare API or toggle `Require all headers` to `enabled` in the Cloudflare dashboard when editing your load balancer.

---

## Enabling Session Affinity from the Cloudflare dashboard

Enable Session Affinity when you [create or edit a load balancer](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/), during the **Hostname** step.

If you enable Session Affinity, choose one of the following options:

* **By Cloudflare cookie only**: Sets a `__cflb` cookie to track the associated endpoint.
* **By Cloudflare cookie and Client IP fallback**: Sets a `__cflb` cookie, but also uses the client IP address when no session affinity cookie is provided.
* **By HTTP header**.

Important

Session Affinity is not supported in [DNS-only mode (gray cloud)](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/). Alternatively, you can use [DNS persistence](https://developers.cloudflare.com/load-balancing/additional-options/dns-persistence/).

---

## Enabling Session Affinity via the Cloudflare API

Session affinity is a property of load balancers, which you can set with the following endpoints:

* [Create a load balancer](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/create/)
* [Edit a load balancer](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/update/)

Customize the behavior of session affinity by using the `session_affinity`, `session_affinity_ttl`, and `session_affinity_attributes` parameters.

To enable session affinity by HTTP header, set the `session_affinity` value to `header` and add your HTTP header names to `session_affinity_attributes.headers`.

For more details on API commands in context, refer to [Create a load balancer with the API](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/).

---

## Endpoint Drain

Drain or remove all traffic from an endpoint without affecting any active customers using endpoint drain. For more details on endpoint drain, refer to [Performing planned maintenance](https://developers.cloudflare.com/load-balancing/additional-options/planned-maintenance/#gradual-rotation).

Important

Endpoint drain is not supported for load balancers in [DNS-only mode (gray cloud)](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/).

## Zero-Downtime Failover

Zero-Downtime Failover automatically sends traffic to endpoints within a pool during transient network issues. This helps reduce errors shown to your users when issues occur in between active health monitors.

You can enable one of three options:

* **None**: No failover will take place and errors may show to your users.
* **Temporary**: Traffic will be sent to other endpoint(s) until the originally pinned endpoint is available.
* **Sticky**: The session affinity cookie is updated and subsequent requests are sent to the new endpoint moving forward as needed.

Note

[Sticky Zero-Downtime Failover](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/#zero-downtime-failover) is not supported for session affinity by HTTP header.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/understand-basics/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/understand-basics/session-affinity/","name":"Session affinity"}}]}
```

---

---
title: Traffic steering
description: Control how traffic is distributed across pools and origins.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Traffic steering

When requests come to your load balancer, it distributes them across your pools and endpoints according to three factors:

1. [Pool and endpoint health](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/): Traffic decisions start with which pools and endpoints are available and should receive traffic.
2. [Global traffic steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/): Policies set on your [load balancer](https://developers.cloudflare.com/load-balancing/load-balancers/) that route traffic to attached and available pools.
3. [Local traffic steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/): These are policies set on each [pool](https://developers.cloudflare.com/load-balancing/pools/) that route traffic to available endpoints within the pool.

When a pool or endpoint becomes unhealthy, your load balancer and pools redistribute traffic according to these same policies.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/understand-basics/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/","name":"Traffic steering"}}]}
```

---

---
title: Hash
description: Distribute requests using hash-based origin steering.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Hash

**Hash steering** guides Cloudflare to send requests to endpoints based on a combination of [endpoint weights](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/#weights) and previous requests from that IP address. Ensures requests from the same IP address will hit the same endpoint, but actual traffic distribution may differ from endpoint weights.

## Limitation when using Workers

Hash Steering relies on the `x-forwarded-for` header to determine the originating IP address of a request. However, when a [Cloudflare Worker](https://developers.cloudflare.com/workers/) is used in front of a load balancer, this can affect how Hash Steering functions.

When a request originates from a browser, it lacks an `x-forwarded-for` header, but if a Worker proxies the request to a load balancer, the header is populated with the Worker's IP instead of the original client IP. Since the Worker's IP — often a Cloudflare public IP — can change between requests, Hash Steering may direct the same client's requests to different endpoints, leading to inconsistent traffic routing.

### Workaround

To ensure Hash Steering works correctly when using a Worker in front of a Load Balancer, manually set the `x-forwarded-for` header in the Worker to the client's original IP address. By manually setting `x-forwarded-for` to `CF-Connecting-IP`, Hash Steering will function as expected, ensuring traffic consistency for end users.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/understand-basics/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/","name":"Traffic steering"}},{"@type":"ListItem","position":5,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/origin-level-steering/","name":"Local traffic steering"}},{"@type":"ListItem","position":6,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/origin-level-steering/hash-origin-steering/","name":"Hash"}}]}
```

---

---
title: Least Outstanding Requests
description: Route to the origin with the fewest active requests.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Least Outstanding Requests

**Least Outstanding Requests steering** allows you to route traffic to endpoints that currently have the lowest number of outstanding requests.

This steering policy selects an endpoint by taking into consideration endpoint weights, as well as each endpoint's number of in-flight requests. Endpoints with more pending requests are weighted proportionately less in relation to others.

Least Outstanding Requests steering is best to use if your endpoints are easily overwhelmed by a spike in concurrent requests. It supports [adaptive routing](https://developers.cloudflare.com/load-balancing/understand-basics/adaptive-routing/) and [session affinity](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/).

## Configure via the API

Pools

```

{

  "origin_steering": {

    "policy": "least_outstanding_requests"

  }

}


```

Refer to the [API documentation](https://developers.cloudflare.com/api/resources/load%5Fbalancers/subresources/pools/methods/update/) for more information on the pool configuration.

Note

Least Outstanding Requests steering can also be configured on a load balancer as a [global traffic steering policy](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/least-outstanding-requests/), taking into account outstanding request counts and `random_steering` weights for pools on the load balancer.

## Limitations

Least Outstanding Requests steering can be configured for pools that are part of [DNS-only load balancers](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/#dns-only-load-balancing), but is only supported in a no-operation form. When endpoint steering logic is applied for a pool on a DNS-only load balancer, all endpoint outstanding request counts are considered to be zero, meaning traffic is served solely based on endpoint weights.

Although it is configurable, it is not recommended to associate pools that use Least Outstanding Requests steering with DNS-only load balancers due to its partial support.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/understand-basics/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/","name":"Traffic steering"}},{"@type":"ListItem","position":5,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/origin-level-steering/","name":"Local traffic steering"}},{"@type":"ListItem","position":6,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/origin-level-steering/least-outstanding-requests-pools/","name":"Least Outstanding Requests"}}]}
```

---

---
title: Random
description: Distribute requests randomly across origins.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Random

**Random steering** sends requests to endpoints purely based on [endpoint weights](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/#weights). Distributes traffic more accurately, but may cause requests from the same IP to hit different endpoints.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/understand-basics/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/","name":"Traffic steering"}},{"@type":"ListItem","position":5,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/origin-level-steering/","name":"Local traffic steering"}},{"@type":"ListItem","position":6,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/origin-level-steering/random-origin-steering/","name":"Random"}}]}
```

---

---
title: Global traffic steering
description: Policies that control how traffic is distributed across pools.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Global traffic steering

Global traffic steering policies decide how a load balancer routes traffic to attached and healthy pools.

  
* [ Standard ](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/standard-options/)
* [ Geo ](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/geo-steering/)
* [ Dynamic ](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/dynamic-steering/)
* [ Proximity ](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/proximity-steering/)
* [ Least Outstanding Requests ](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/least-outstanding-requests/)

## EDNS Client Subnet (ECS) support

 EDNS Client Subnet (ECS)  support provides customers with more control over location-based steering during gray-clouded DNS resolutions and can be used for proximity or geo (country) steering.

Customers can configure their load balancer using the `location_strategy` parameter, which includes the properties `prefer_ecs` and `mode`.

`prefer_ecs` determines whether the ECS geolocation should be preferred as the authoritative location.

| Type        | Description                                                                            |
| ----------- | -------------------------------------------------------------------------------------- |
| "always"    | Always prefers ECS.                                                                    |
| "never"     | Never prefers ECS.                                                                     |
| "proximity" | Prefers ECS only when steering\_policy="proximity".                                    |
| "geo"       | Prefers ECS only when steering\_policy="geo" and only supports country-level steering. |

`mode` determines the authoritative location when ECS is not preferred, does not exist in the request, or its geolocation lookup is unsuccessful.

| Type           | Description                                                                                                             |
| -------------- | ----------------------------------------------------------------------------------------------------------------------- |
| "pop"          | Uses the Cloudflare PoP location.                                                                                       |
| "resolver\_ip" | Uses the DNS resolver geolocation data. If the geolocation lookup is unsuccessful, it uses the Cloudflare PoP location. |

Note

ECS support applies to DNS-only load balancers.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/understand-basics/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/","name":"Traffic steering"}},{"@type":"ListItem","position":5,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/steering-policies/","name":"Global traffic steering"}}]}
```

---

---
title: Dynamic
description: Route traffic to the fastest pool based on health check latency.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Dynamic

**Dynamic steering** uses health monitor data to identify the fastest pool for a given Cloudflare Region or data center.

Dynamic steering creates Round Trip Time (RTT) profiles based on an exponential weighted moving average (EWMA) of RTT to determine the fastest pool. If there is no current RTT data for your pool in a region or colocation center, Cloudflare directs traffic to the pools in failover order.

RTT values are collected each time a health probe request is made and based on the response from the endpoint to the monitor request. When a request is made, Cloudflare inspects the RTT data and uses it to sort pools by their RTT values.

When enabling Dynamic steering the first time for a pool, allow 10 minutes for the change to take effect while Cloudflare builds an RTT profile for that pool.

For TCP health monitors, calculated latency may not reflect the true latency to the endpoint if you are terminating TCP at a cloud provider edge location.

The diagram below shows how Cloudflare would route traffic to the pool with the lowest EWMA among three regions: Eastern North America, Europe, and Australia. In this case, the ENAM pool is selected because it has the lowest RTT.

![Dynamic steering routes traffic to the fastest available pool](https://developers.cloudflare.com/_astro/traffic-steering-2.CEeFHZfg_5RxfF.webp) 

Note

To ensure dynamic steering works as expected, the [Health Monitor Region](https://developers.cloudflare.com/load-balancing/monitors/#health-monitor-regions) must be set to **All Regions**. The Enterprise-only **All Data Centers** option is also a viable alternative.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/understand-basics/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/","name":"Traffic steering"}},{"@type":"ListItem","position":5,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/steering-policies/","name":"Global traffic steering"}},{"@type":"ListItem","position":6,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/steering-policies/dynamic-steering/","name":"Dynamic"}}]}
```

---

---
title: Geo
description: Route traffic to pools based on visitor geographic location.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Geo

**Geo steering** directs traffic to pools tied to specific countries, regions, or — for Enterprise customers only — data centers.

This option is extremely useful when you want site visitors to access the endpoint closest to them, which improves page-loading performance.

Note

Custom load balancing rules are incompatible with Geo steering. As a result, any custom rule applied to Geo-steered Load Balancers will not function as expected.

## Pool assignment

You can assign multiple pools to the same area and the load balancer will use them in failover order. Any options not explicitly defined — whether in data centers, countries, or regions — will fall back to using default pools and failover.

### Region steering

Cloudflare has [13 geographic regions](https://developers.cloudflare.com/load-balancing/reference/region-mapping-api/#list-of-load-balancer-regions) that span the world. The region of a client is determined by the region of the Cloudflare data center that answers the client’s DNS query.

Warning

If you add a pool to a region, you cannot [delete this pool](https://developers.cloudflare.com/load-balancing/pools/create-pool/#delete-a-pool) until you remove it from the **Geo steering** configuration. The configuration is **not** automatically removed when you change to a different **Traffic Steering** method.

* [ Dashboard ](#tab-panel-9186)
* [ API ](#tab-panel-9187)

When [creating or editing a load balancer](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/):

1. Go to the **Traffic steering** step.
2. Select **Geo steering**.
3. For **Region**, select a region > **Add Region**.
4. Select **Edit**.
5. Select a pool > **Add Pool**.
6. If adding multiple pools, re-order them into your preferred failback order.
7. (optional) Add more regions if needed.

Use the `regions_pool` property of the [Update Load Balancers](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/update/) command to specify an array of regions. Specify each region using the [appropriate region code](https://developers.cloudflare.com/load-balancing/reference/region-mapping-api/#list-of-load-balancer-regions) followed by a list of endpoints to use for that region.

In the example below, `WNAM` and `ENAM` represent the West and East Coasts of North America, respectively.

Request

```

// PUT /zones/:zone_id/load_balancers

{

  "description": "Load Balancer for www.example.com",

  "name": "www.example.com",

  "ttl": 30,

  "proxied": true,

  "fallback_pool": "ff02c959d17f7bb2b1184a202e3c0af7",

  "default_pools": [

    "17b5962d775c646f3f9725cbc7a53df4",

    "ff02c959d17f7bb2b1184a202e3c0af7"

  ],

  "region_pools": {

    "WNAM": [

      "17b5962d775c646f3f9725cbc7a53df4",

      "ff02c959d17f7bb2b1184a202e3c0af7"

    ],

    "ENAM": [

      "17b5962d775c646f3f9725cbc7a53df4",

      "ff02c959d17f7bb2b1184a202e3c0af7"

    ],

    "EEU": [

      "ff02c959d17f7bb2b1184a202e3c0af7",

      "17b5962d775c646f3f9725cbc7a53df4"

    ]

  }

}


```

If you only define `WNAM`, then traffic from the East Coast will be routed to the `default_pools`. You can test this using a client in each of those locations.

### Country steering

* [ Dashboard ](#tab-panel-9188)
* [ API ](#tab-panel-9189)

When [creating or editing a load balancer](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/):

1. Follow the [create a load balancer procedure](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/#create-a-load-balancer) until you reach the **Traffic steering** step.
2. Select **Geo steering**.
3. For **Country**, select a country > **Add Region**.
4. Select **Edit**.
5. Select a pool > **Add Pool**.
6. If adding multiple pools, re-order them into your preferred failback order.
7. (optional) Add more countries if needed.

When creating a load balancer [via the API](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/create/), include the `country_pools` object to map countries to a list of pool IDs (ordered by their failover priority).

To get a list of country codes, use the [Region API](https://developers.cloudflare.com/load-balancing/reference/region-mapping-api/).

Any country not explicitly defined will fall back to using the corresponding `region_pool` mapping (if it exists), then to the associated default pools.

### PoP steering

When creating a load balancer [via the API](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/create/), include the `pop_pools` object to map Cloudflare data centers to a list of pool IDs (ordered by their failover priority).

For help finding data center identifiers, refer to [this community thread ↗](https://community.cloudflare.com/t/is-there-a-way-to-retrieve-cloudflare-pops-list-and-locations-programmatically/234643).

Any data center not explicitly defined will fall back to using the corresponding `country_pool`, then `region_pool` mapping (if it exists), and finally to associated default pools.

Note

PoP steering is only available to Enterprise customers and only accessible via the API.

### Failover behavior

A fallback pool will be used if there is only one pool in the same region and it is unavailable. If there are multiple pools in the same region, the order of the pools will be respected. For example, if the first pool is unavailable, the second pool will be used.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/understand-basics/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/","name":"Traffic steering"}},{"@type":"ListItem","position":5,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/steering-policies/","name":"Global traffic steering"}},{"@type":"ListItem","position":6,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/steering-policies/geo-steering/","name":"Geo"}}]}
```

---

---
title: Least Outstanding Requests
description: Route traffic to the pool with the fewest pending requests.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Least Outstanding Requests

**Least Outstanding Requests steering** allows you to route traffic to pools that currently have the lowest number of outstanding requests.

This steering policy selects a pool by taking into consideration `random_steering` weights, as well as each pool's number of in-flight requests. Pools with more pending requests are weighted proportionately less in relation to others.

Least Outstanding Requests steering is best to use if your pools are easily overwhelmed by a spike in concurrent requests. This steering method lends itself to applications that value server health above latency, geographic alignment, or other metrics. It takes into account the [pool's health status](https://developers.cloudflare.com/load-balancing/understand-basics/health-details/#how-a-pool-becomes-unhealthy), [adaptive routing](https://developers.cloudflare.com/load-balancing/understand-basics/adaptive-routing/), and [session affinity](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/).

## Configure via the API

Load Balancers

```

{

  "steering_policy": "least_outstanding_requests"

}


```

Refer to the [API documentation](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/update/) for more information on the load balancer configuration.

Note

Least Outstanding Requests steering can also be configured on a pool as a [local traffic steering policy](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/least-outstanding-requests-pools/), taking into account outstanding request counts and weights for endpoints within the pool.

## Limitations

Least Outstanding Requests steering can be configured for [DNS-only load balancers](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/#dns-only-load-balancing), but is only supported in a no-operation form. For DNS-only load balancers, all pool outstanding request counts are considered to be zero, meaning traffic is served solely based on `random_steering` weights.

Although it is configurable, it is not recommended to use Least Outstanding Requests steering for DNS-only load balancers due to its partial support.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/understand-basics/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/","name":"Traffic steering"}},{"@type":"ListItem","position":5,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/steering-policies/","name":"Global traffic steering"}},{"@type":"ListItem","position":6,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/steering-policies/least-outstanding-requests/","name":"Least Outstanding Requests"}}]}
```

---

---
title: Proximity
description: Route traffic to the nearest pool by geographic proximity.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Proximity

**Proximity steering** routes visitors or internal services to the closest physical data center.

To use proximity steering on a load balancer, you first need to add GPS coordinates to each pool.

## When to add proximity steering

* For new pools, add GPS coordinates when you create a pool.
* For existing pools, add GPS coordinates when [managing pools](https://developers.cloudflare.com/load-balancing/pools/create-pool/#edit-a-pool) or in the **Add Traffic steering** step of [creating a load balancer](https://developers.cloudflare.com/load-balancing/load-balancers/create-load-balancer/).

## How to add proximity steering

To add coordinates when creating or editing a pool:

1. Click the _Configure coordinates for Proximity Steering_ dropdown.
2. Enter the latitude and longitude or drag a marker on the map.
3. Select **Save**.

Warning:

For accurate proximity steering, add GPS coordinates to all pools within the same load balancer.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/understand-basics/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/","name":"Traffic steering"}},{"@type":"ListItem","position":5,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/steering-policies/","name":"Global traffic steering"}},{"@type":"ListItem","position":6,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/steering-policies/proximity-steering/","name":"Proximity"}}]}
```

---

---
title: Standard
description: Standard traffic steering options including failover and random.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Standard

**Standard steering** policies include **Off - Failover** and **Random**.

These are the only steering policies available to non-Enterprise customers who have not purchased **Traffic steering**.

## Off - Failover

Failover steering uses the pool order to determine failover priority (the failover order).

Failover directs traffic from unhealthy pools — determined by [health monitors](https://developers.cloudflare.com/load-balancing/monitors/) and the **Health Threshold** — to the next healthy pool in the configuration. Customers commonly use this option to set up [active - passive failover](https://developers.cloudflare.com/load-balancing/load-balancers/common-configurations/#active---passive-failover).

If all pools are marked unhealthy, Load Balancing will direct traffic to the fallback pool. The default fallback pool is the last pool listed in the Load Balancing configuration.

If no monitors are attached to the load balancer, it will direct traffic to the primary pool exclusively.

### Failback behavior

In an active/standby setup, with two origin pools:

* Traffic always routes to Pool 1 (the primary pool) unless it becomes unhealthy.
* If Pool 1 is marked unhealthy, traffic shifts to Pool 2 (the standby pool).
* Once Pool 1 becomes healthy again, traffic automatically shifts back to Pool 1, assuming no [session affinity](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/) or other settings require subsequent requests to stay at Pool 2.

This behavior is known as failback and ensures traffic resumes normal routing when the primary pool recovers.

## Random steering

Choose **Random** to route traffic to a healthy pool at random. Customers can use this option to set up [active - active failover](https://developers.cloudflare.com/load-balancing/load-balancers/common-configurations/#active---active-failover) (also known as round robin), where traffic is split equally between multiple pools.

Similar to setting Weights to direct the amount of traffic going to each endpoint, customers can also set Weights on pools via the [API's](https://developers.cloudflare.com/api/resources/load%5Fbalancers/methods/create/) `random_steering` object to determine the percentage of traffic sent to each pool.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/load-balancing/","name":"Load Balancing"}},{"@type":"ListItem","position":3,"item":{"@id":"/load-balancing/understand-basics/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/","name":"Traffic steering"}},{"@type":"ListItem","position":5,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/steering-policies/","name":"Global traffic steering"}},{"@type":"ListItem","position":6,"item":{"@id":"/load-balancing/understand-basics/traffic-steering/steering-policies/standard-options/","name":"Standard"}}]}
```

---

---
title: Cloudflare Smart Shield
description: Use Smart Shield to protect your origin server, improve content availability, and reduce network latency.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare Smart Shield

Protect your origin server, reduce load, and improve content delivery performance.

Every request that reaches your origin server costs resources — bandwidth, compute, and connections. When traffic spikes or your content is requested from many locations simultaneously, your origin can become a bottleneck. Smart Shield is a bundle of origin protection and performance features that reduce the number of requests and connections between Cloudflare's network and your origin server.

Smart Shield includes [Smart Tiered Cache](https://developers.cloudflare.com/smart-shield/configuration/smart-tiered-cache/), which organizes Cloudflare data centers into upper-tier and lower-tier groups so that only upper-tier data centers contact your origin for uncached content. Combined with [connection reuse](https://developers.cloudflare.com/smart-shield/concepts/connection-reuse/), which packages multiple requests into a single connection to your origin, Smart Shield reduces both the volume of origin requests and the number of open connections.

Depending on your [package tier](https://developers.cloudflare.com/smart-shield/get-started/#packages-and-availability), Smart Shield can also include:

* [Argo Smart Routing](https://developers.cloudflare.com/smart-shield/configuration/argo/) — routes traffic through the fastest network paths to reduce latency.
* [Regional Tiered Cache](https://developers.cloudflare.com/smart-shield/configuration/regional-tiered-cache/) — adds a regional cache layer between lower-tier and upper-tier data centers for geographic data locality (Enterprise plans, or Smart Shield Advanced).
* [Cache Reserve](https://developers.cloudflare.com/smart-shield/configuration/cache-reserve/) — persistent cache storage that reduces cache misses for infrequently accessed content.
* [Health Checks](https://developers.cloudflare.com/smart-shield/configuration/health-checks/) — monitors your origin server availability (Pro plans and above).
* [Dedicated CDN Egress IPs](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/) — reserved IP addresses for origin allowlisting (Enterprise).

For a visual overview of how these features work together, refer to the [network diagram](https://developers.cloudflare.com/smart-shield/concepts/network-diagram/).

Learn how to [get started](https://developers.cloudflare.com/smart-shield/get-started/).

---

## Related products

**[Cache](https://developers.cloudflare.com/cache/)** 

Cache stores copies of frequently accessed content (such as images, videos, or webpages) in geographically distributed data centers that are located closer to end users than origin servers, improving website performance.

**[Observatory](https://developers.cloudflare.com/speed/observatory/)** 

Observatory uses synthetic tests and real user data to assess the performance of your website, producing different metrics and insights. Cloudflare then uses this analysis to recommend optimizations that best address your performance issues.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}}]}
```

---

---
title: Get started
description: Enable Smart Shield and configure origin protection features for your domain.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

Smart Shield reduces the load on your origin server and improves content delivery by consolidating requests through Cloudflare's caching infrastructure. It is available to all customers as an opt-in configuration.

## Before you begin

* You must have a Cloudflare account and [onboard your domain](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/).
* Verify that DNS records for the domain you want to protect are set to [proxied](https://developers.cloudflare.com/dns/proxy-status/). Smart Shield operates within Cloudflare's reverse proxy, so traffic from DNS-only records is not routed through it.

## Steps

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Speed** \> **Smart Shield**.
3. (Optional) Explore the different [available packages](#packages-and-availability).
4. Select **Get started for free** or choose a different package and select **Continue** to proceed to the guided onboarding flow.

After setup, you can monitor origin performance and cache effectiveness through the [Observatory](https://developers.cloudflare.com/speed/observatory/) dashboard.

## Packages and availability

Pro, Business, and Enterprise customers have access to [Health Checks](https://developers.cloudflare.com/smart-shield/configuration/health-checks/) for monitoring origin availability across all packages.

### Smart Shield

The base package for reducing origin load through caching and connection optimization.

* Includes [Smart Tiered Cache](https://developers.cloudflare.com/smart-shield/configuration/smart-tiered-cache/) and [Connection Reuse](https://developers.cloudflare.com/smart-shield/concepts/connection-reuse/).

### Smart Shield + Argo

Adds network path optimization on top of the base package. Use when visitors are geographically distant from the origin server.

* Includes [Smart Tiered Cache](https://developers.cloudflare.com/smart-shield/configuration/smart-tiered-cache/), [Connection Reuse](https://developers.cloudflare.com/smart-shield/concepts/connection-reuse/), and [Argo Smart Routing](https://developers.cloudflare.com/smart-shield/configuration/argo/).

### Smart Shield Advanced

The full package with additional caching customization through regional and persistent storage options.

* Includes [Smart Tiered Cache](https://developers.cloudflare.com/smart-shield/configuration/smart-tiered-cache/), [Connection Reuse](https://developers.cloudflare.com/smart-shield/concepts/connection-reuse/), [Argo Smart Routing](https://developers.cloudflare.com/smart-shield/configuration/argo/), [Regional Tiered Cache](https://developers.cloudflare.com/smart-shield/configuration/regional-tiered-cache/), and [Cache Reserve](https://developers.cloudflare.com/smart-shield/configuration/cache-reserve/).

Regional Tiered Cache for Enterprise

Enterprise customers have access to [Regional Tiered Cache](https://developers.cloudflare.com/smart-shield/configuration/regional-tiered-cache/) as part of their plan, regardless of which Smart Shield package they use. Free, Pro, and Business plans receive Regional Tiered Cache through Smart Shield Advanced.

Dedicated CDN Egress IPs

Enterprise customers also have the option to configure [Dedicated CDN Egress IPs](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/), allowing you to increase origin security by only allowing traffic from a small list of IP addresses. If you are interested, reach out to your account team.

## Further reading

* [ Network diagram ](https://developers.cloudflare.com/smart-shield/concepts/network-diagram/)
* [ Connection reuse ](https://developers.cloudflare.com/smart-shield/concepts/connection-reuse/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/get-started/","name":"Get started"}}]}
```

---

---
title: Connection reuse
description: How Smart Shield reduces origin connections by packaging multiple requests into one.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Connection reuse

Smart Shield reduces the number of connections between Cloudflare and your origin server by batching multiple requests through shared connections. When requests from an [upper-tier data center](https://developers.cloudflare.com/smart-shield/configuration/smart-tiered-cache/) — the layer of Cloudflare's cache that sits closest to your origin — need to reach your server, Smart Shield sends them over a single connection instead of opening a new connection for each request. This reduces overall connections to your origin by 30% on average, which lowers resource consumption on your origin and reduces the risk of connection exhaustion under high traffic.

For more information, refer to the [Smart Shield announcement blog post ↗](https://blog.cloudflare.com/introducing-observatory-and-smart-shield/#protecting-and-accelerating-origins-with-smart-connection-reuse).

## About connection reuse

Every HTTP request requires a TCP connection between a client and a server. Each connection is identified by a pair of network addresses: the source IP address and port, and the destination IP address and port. Opening a new TCP connection has overhead — it requires a handshake between client and server, and a TLS negotiation if the connection is encrypted.

Connection reuse (also called persistent connections or keep-alive) avoids this overhead by sending multiple HTTP requests over a single TCP connection instead of opening a new connection for each request. HTTP/1.1 made this the default behavior.

For example, when a browser opens a connection to `shop.example.com`, the page may reference dozens of additional resources — stylesheets, images, scripts, and other files. Without connection reuse, each resource would require its own TCP connection. With connection reuse, all of these requests flow through the same connection.

### Connection coalescing (HTTP/2)

With HTTP/2, connection reuse extends further through connection coalescing. This allows requests for different hostnames to share a single connection, as long as two conditions are met:

* The hostnames resolve to the same destination IP address and port.
* The TLS certificate on the server covers both hostnames (for example, a certificate that lists both `shop.example.com` and `blog.example.com` in its Subject Alternative Names).

This means a connection originally opened for `shop.example.com` can also carry requests for `blog.example.com`, reducing the total number of connections to your origin even further.

## Connection reuse and Dedicated CDN Egress IPs

Connection reuse and connection coalescing are also considered when allocating your [Dedicated CDN Egress IPs](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/concepts/connection-reuse/","name":"Connection reuse"}}]}
```

---

---
title: Network diagram
description: Visual overview of Smart Shield features and their role in origin protection.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Network diagram

The diagram below shows how requests flow through the Cloudflare network when Smart Shield is active, and where each feature applies along that path.

![Network diagram of requests being processed with all Smart Shield features](https://developers.cloudflare.com/_astro/network-diagram.PeUYDGK__Z2qTCdR.webp) 

Requests from visitors first reach a nearby lower-tier data center. For static (cacheable) content, the lower-tier checks its local cache. On a cache miss, the request moves to an upper-tier data center — selected by [Smart Tiered Cache](https://developers.cloudflare.com/smart-shield/configuration/smart-tiered-cache/) based on lowest latency to your origin. If [Regional Tiered Cache](https://developers.cloudflare.com/smart-shield/configuration/regional-tiered-cache/) is configured, a regional hub is checked before the upper-tier. Persistent storage through [Cache Reserve](https://developers.cloudflare.com/smart-shield/configuration/cache-reserve/) provides a final cache layer before requesting content from your origin.

For dynamic (non-cacheable) requests, [Argo Smart Routing](https://developers.cloudflare.com/smart-shield/configuration/argo/) finds the fastest network path to your origin. Between Cloudflare's upper-tier data centers and your origin, [connection reuse](https://developers.cloudflare.com/smart-shield/concepts/connection-reuse/) packages multiple requests into a single connection, reducing the total number of connections your origin handles.

[Health Checks](https://developers.cloudflare.com/smart-shield/configuration/health-checks/) run from multiple data centers to monitor whether your origin is online and responsive. [Dedicated CDN Egress IPs](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/) provide reserved IP addresses for traffic from Cloudflare to your origin, allowing you to restrict your origin firewall to a small allowlist.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/concepts/network-diagram/","name":"Network diagram"}}]}
```

---

---
title: Argo Smart Routing
description: Route traffic through the fastest network paths to reduce latency to your origin.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Argo Smart Routing

Availability

Available with Smart Shield + Argo and Smart Shield Advanced.

Argo Smart Routing detects real-time network issues and routes your web traffic across the most efficient network path, avoiding congestion.

Cloudflare provides analytics to show the performance benefits of Argo Smart Routing.

Analytics collects data based on the time-to-first-byte (TTFB) from your origin to the Cloudflare network. TTFB is the delay between when Cloudflare sends a request to your server and when it receives the first byte in response. Argo Smart Routing optimizes your server's network transit time to minimize this delay.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/configuration/argo/","name":"Argo Smart Routing"}}]}
```

---

---
title: Cache Reserve
description: Persist cached content in R2 storage to eliminate cache evictions and origin fetches.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache Reserve

Availability

Available with Smart Shield Advanced.

Cache Reserve is a large, persistent data store [implemented on top of R2](https://developers.cloudflare.com/r2/). By pushing a single button in the dashboard, your website's cacheable content will be written to Cache Reserve.

In the same way that Tiered Cache builds a hierarchy of caches between your visitors and your origin, Cache Reserve serves as the ultimate upper-tier cache, that will reserve storage space for your assets for as long as you want. This ensures that your content is served from cache longer, shielding your origin from unneeded egress fees.

Smart Shield Advanced includes 2 TB of storage for Cache Reserve.

## Asset eligibility

Not all assets are eligible for Cache Reserve. To be admitted into Cache Reserve, assets must:

* Be cacheable, according to Cloudflare's standard [cacheability factors](https://developers.cloudflare.com/cache/).
* Have a freshness time-to-live (TTL) of at least 10 hours (set by any means such as Cache-Control / [CDN-Cache-Control](https://developers.cloudflare.com/cache/concepts/cache-control/) origin response headers, [Edge Cache TTL](https://developers.cloudflare.com/cache/how-to/edge-browser-cache-ttl/#edge-cache-ttl), [Cache TTL By Status](https://developers.cloudflare.com/cache/how-to/configure-cache-status-code/), or [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/)),
* Have a Content-Length response header.
* When using [Image transformations](https://developers.cloudflare.com/images/optimization/hosted-images/create-variants/), original files are eligible for Cache Reserve, but resized file variants are not eligible because transformations happen after Cache Reserve in the response flow.

## Limits

* Cache Reserve file limits are the same as [R2 limits](https://developers.cloudflare.com/r2/platform/limits/). Note that [CDN cache limits](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#customization-options-and-limits) still apply. Assets larger than standard limits will not be stored in the standard CDN cache, so these assets will incur Cache Reserve operations costs far more frequently.
* Origin Range requests are not supported at this time from Cache Reserve.
* [Vary for images](https://developers.cloudflare.com/cache/advanced-configuration/vary-for-images/) is currently not compatible with Cache Reserve.
* Requests to [R2 public buckets linked to a zone's domain](https://developers.cloudflare.com/r2/buckets/public-buckets/) will not use Cache Reserve. Enabling Cache Reserve for the connected zone will use Cache Reserve only for requests not destined for the R2 bucket.
* Cache Reserve makes requests for uncompressed content directly from the origin. Unlike the standard Cloudflare CDN, Cache Reserve does not include the `Accept-Encoding: gzip` header when sending requests to the origin.
* Cache Reserve is bypassed when using the Cloudflare [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/) setup.

## Delete data

You can remove all data stored in Cache Reserve. In most cases, deletion takes around 24 hours to be completed.

1. Select the three dots next to Cache Reserve in your Smart Shield configurations.
2. Choose **View details** to open the Cache Reserve sidebar.
3. Make sure to pause Cache Reserve.
4. Select **Delete data** and then **Save**.
5. Select **Delete** again in the dialog to confirm.

Note

If you want to purge your cache instead, refer to [cache configurations](https://developers.cloudflare.com/cache/how-to/purge-cache/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/configuration/cache-reserve/","name":"Cache Reserve"}}]}
```

---

---
title: Cache Reserve analytics
description: View Cache Reserve storage, read, and write operation metrics.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache Reserve analytics

Cache Reserve Analytics provides insights regarding your Cache Reserve usage. It allows you to check what content is stored in Cache Reserve, how often it is being accessed, how long it has been there and how much egress from your origin it is saving you.

You have access to the following metrics:

* **Egress savings (bandwidth)** \- is an estimation based on response bytes served from Cache Reserve that did not need to be served from your origin server. These are represented as cache hits.
* **Requests served by Cache Reserve** \- is the number of requests served by Cache Reserve (total).
* **Data storage summary** \- is based on a representative sample of requests. Refer to [Sampling](https://developers.cloudflare.com/analytics/graphql-api/sampling/) for more details about how Cloudflare samples data.  
   * **Current data stored** \- is the data stored (currently) over time.  
   * **Aggregate storage usage** \- is the total of storage used for the selected timestamp.
* **Operations** \- Class A (writes) and Class B (reads) operations over time.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/configuration/cache-reserve/","name":"Cache Reserve"}},{"@type":"ListItem","position":5,"item":{"@id":"/smart-shield/configuration/cache-reserve/analytics/","name":"Cache Reserve analytics"}}]}
```

---

---
title: Cache Reserve operations
description: How Cache Reserve read, write, and delete operations work with R2 storage.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache Reserve operations

Operations are performed by Cache Reserve on behalf of the user to write data from the origin to Cache Reserve and to pass that data downstream to other parts of Cloudflare’s network. These operations are managed internally by Cloudflare.

#### Class A operations (writes)

Class A operations are performed based on cache misses from Cloudflare’s CDN. When a request cannot be served from cache, it will be fetched from the origin and written to cache reserve as well as our edge caches on the way back to the visitor.

#### Class B operations (reads)

Class B operations are performed when data needs to be fetched from Cache Reserve to respond to a miss in the edge cache.

#### Purge

Asset purges are free operations.

Cache Reserve will be instantly purged along with edge cache when you send a purge by URL request. Refer to [cache configurations](https://developers.cloudflare.com/cache/how-to/purge-cache/) for details.

Other purge methods, such as purge by tag, host, prefix, or purge everything will force an attempt to [revalidate](https://developers.cloudflare.com/cache/concepts/cache-responses/#revalidated) on the subsequent request for the Cache Reserve asset. Note that assets purged this way will still incur storage costs until their retention TTL expires.

Note

Note this differs from the standard CDN's purge by tag, host, or prefix features which force a cache miss, requiring the origin to deliver the asset in full.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/configuration/cache-reserve/","name":"Cache Reserve"}},{"@type":"ListItem","position":5,"item":{"@id":"/smart-shield/configuration/cache-reserve/operations/","name":"Cache Reserve operations"}}]}
```

---

---
title: Dedicated CDN Egress IPs
description: Use reserved egress IP addresses for origin allowlisting and increased security.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Dedicated CDN Egress IPs

Enterprise customers can leverage dedicated egress[1](#user-content-fn-1) IPs for layer 7 [WAF](https://developers.cloudflare.com/waf/) and CDN services, as well as [Spectrum](https://developers.cloudflare.com/spectrum/). The egress IPs are reserved exclusively for your account so that you can increase your origin security by only allowing traffic from a small list of IP addresses.

Note

If you are interested in using Smart Shield Advanced with Dedicated CDN Egress IPs, reach out to your account team.

Dedicated CDN Egress IPs was formerly known as Cloudflare Aegis ([release blog post ↗](https://blog.cloudflare.com/cloudflare-aegis/)).

## Benefits

With Dedicated CDN Egress IPs, you can:

* Lock down your network firewall to only allow traffic from your dedicated IPs.
* Use [Cloudflare Access and CNI](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/other-products/#access-and-cni) to secure your applications without installing software or customizing code on your server.
* Ensure only authorized [Workers](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/other-products/#workers) can access your origin services.

## Scope

You can assign Dedicated CDN Egress IPs to single or multiple Cloudflare zones, and across different Cloudflare accounts.

Dedicated CDN Egress IPs are included within [BGP advertisement over CNI](https://developers.cloudflare.com/network-interconnect/).

Each dedicated egress pool can consist of either IPs from a [BYOIP prefix](https://developers.cloudflare.com/byoip/) or Cloudflare-leased IPs. A single dedicated egress pool cannot contain both BYOIPs and leased IPs. Also, a single BYOIP prefix can be used for either CDN ingress or CDN egress, but not both.

## Resources

* [ How it works ](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/how-it-works/)
* [ Setup ](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/setup/)
* [ IPs utilization ](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/ips-utilization/)
* [ Use with other Cloudflare products ](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/other-products/)

## Footnotes

1. From Cloudflare to your origin. Refer to [how it works](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/how-it-works/egress-ips/) for details. [↩](#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":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/configuration/dedicated-egress-ips/","name":"Dedicated CDN Egress IPs"}}]}
```

---

---
title: Connection forwarding
description: How IPv4 egress traffic is forwarded between Cloudflare data centers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Connection forwarding

Since IPv6 address ranges are deployed globally, no forwarding is needed.

For IPv4 traffic, based on [IPs allocation](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/how-it-works/egress-ips/#ips-allocation), not all egress data centers will have access to an applicable dedicated CDN egress IP.

Dedicated CDN egress IPs do not forward to another location in response to traffic spikes. Instead, each IPv4 can be split across up to four locations, where some of these locations may have multiple data centers. IP capacity in each data center can also be adjusted in accordance with the amount of traffic that reaches each location.

After a request reaches Cloudflare on an ingress data center, and the cache service sends a request for the egress router to connect to your origin, the following scenarios are possible.

### Traffic can egress from the same server

If the server running the egress router has access to an applicable dedicated CDN egress IP, traffic egresses from that server.

flowchart LR
        accTitle: Dedicated CDN Egress IPs and connection forwarding
        accDescr: Diagram showing IPv4 connection forwarding for Dedicated CDN Egress IPs - Same data center.
        A[Client]
        subgraph Data center A
        X[(Cache service)] --> B[(Egress router <br/> <small>*has applicable IP</small>)]
        end
        C[(Origin server)]

        A --ingress--> X
        B --egress--> C

### Connection forwarding is needed

If the server does not have access to an applicable IP, the following options are checked and the first that is possible will take place:

* Another server in the same data center has access to an applicable IP and the connection is forwarded to that server.

flowchart LR
        accTitle: Dedicated CDN Egress IPs and connection forwarding
        accDescr: Diagram showing IPv4 connection forwarding for Dedicated CDN Egress IPs - Same data center.
        A[Client]
        subgraph Data center A
        X[(Cache service)] --> B[(Egress router <br/> <small>*no applicable IP</small>)]
        B --> Y[(Egress server <br/> <small>*has applicable IP</small>)]
        end
        C[(Origin server)]

        A --ingress--> X
        Y --egress--> C

* Another data center in the same location has access to an applicable IP and the connection is forwarded to that data center.

flowchart LR
        accTitle: Dedicated CDN Egress IPs and connection forwarding
        accDescr: Diagram showing IPv4 connection forwarding for Dedicated CDN Egress IPs - Different data center.
        A[Client]
        subgraph Location 1
        subgraph Data center A
        X[(Cache service)] --> B[(Egress router <br/> <small>*no applicable IP</small>)]
        end
        subgraph Data center B
        B --> Y[(Egress server <br/> <small>*has applicable IP</small>)]
        end
        end
        C[(Origin server)]


        A --ingress--> X
        Y --egress--> C

* Another data center in a different location has access to an applicable IP. The closest location is selected and connection is forwarded to that location.

flowchart LR
        accTitle: Dedicated CDN Egress IPs and connection forwarding
        accDescr: Diagram showing IPv4 connection forwarding for Dedicated CDN Egress IPs - Different location.
        A[Client]
        subgraph Location 1
          subgraph Data center A
          X[(Cache service)] --> B[(Egress router <br/> <small>*no applicable IP</small>)]
          end
        end
        subgraph Location 2
          subgraph Data center C
            B --> Y[(Egress server <br/> <small>*has applicable IP</small>)]
          end
        end
        C[(Origin server)]


        A --ingress--> X
        Y --egress--> C

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/configuration/dedicated-egress-ips/","name":"Dedicated CDN Egress IPs"}},{"@type":"ListItem","position":5,"item":{"@id":"/smart-shield/configuration/dedicated-egress-ips/how-it-works/","name":"How it works"}},{"@type":"ListItem","position":6,"item":{"@id":"/smart-shield/configuration/dedicated-egress-ips/how-it-works/connection-forwarding/","name":"Connection forwarding"}}]}
```

---

---
title: Egress IPs
description: How egress IPs are allocated across IPv4 and IPv6 for your account.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Egress IPs

When you use Cloudflare [as a reverse proxy](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/#cloudflare-as-a-reverse-proxy), [Cloudflare's global network ↗](https://www.cloudflare.com/network/) sits between client requests and your origin servers.

flowchart LR
        accTitle: Cloudflare as a reverse proxy
        accDescr: Diagram showing Cloudflare's network between clients and the origin server.
        A[Client] <--> B((Cloudflare))<--> C[(Origin server)]

Zooming into what happens as a request routes through Cloudflare, you can consider two parts of the process: ingress and egress.

flowchart LR
        accTitle: Cloudflare as a reverse proxy
        accDescr: Diagram showing Cloudflare's network between clients and the origin server.
        A[Client] --ingress--> B((Cloudflare))--egress--> C[(Origin server)]

Ingress refers to the data center where the client request lands on, based on Internet routing. From there on, the request will be processed according to your Cloudflare configurations and, if needed, a connection to the origin will be initiated via an egress data center.

Traditionally, Cloudflare maintains a very large pool of egress IPs that are used by all Cloudflare customers and are [publicly documented ↗](https://www.cloudflare.com/ips/). With Dedicated CDN Egress IPs, Cloudflare connects to your origin using IPs that are reserved for you.

## BYOIP or Cloudflare-leased

Each dedicated CDN egress IP pool can consist of either IPs from a [BYOIP prefix](https://developers.cloudflare.com/byoip/) or Cloudflare-leased IPs. A single dedicated CDN egress IP pool cannot contain both BYOIPs and leased IPs.

You can find your leased dedicated IPs for CDN egress on the dashboard under [**Address space** \> **Leased IPs** ↗](https://dash.cloudflare.com/?to=/:account/ip-addresses/address-space).

If you are using BYOIP, refer to **BYOIP prefixes** instead.

## IPs allocation

Dedicated CDN Egress IPs support both IPv4 and IPv6 addresses.

IPv6 address ranges are deployed globally, meaning your dedicated IPv6 addresses can be used for connections from Cloudflare to your origin servers across all Cloudflare data centers.

China exception

Dedicated CDN Egress IPs are currently **not** available in the [Cloudflare China Network](https://developers.cloudflare.com/china-network/).

For IPv4 addresses, you should work with your account team to choose the locations where each IP should be deployed. Ideally, your dedicated IPv4 addresses should be placed near your origin servers and adjusted to the amount of traffic expected for each region.

Refer to [connection forwarding](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/how-it-works/connection-forwarding/) to understand how requests are processed when reaching different Cloudflare data centers.

### Connections to your origin

Each Dedicated CDN Egress IP can support 40,000 concurrent connections per origin IP port. For example, if you have one dedicated IP and two origins (A and B), this single IP can support 40,000 concurrent connections to origin A, while simultaneously supporting 40,000 concurrent connections to origin B.

Dedicated CDN Egress IPs also benefit from [connection reuse and coalescing](https://developers.cloudflare.com/smart-shield/concepts/connection-reuse/).

GraphQL Analytics API allows you to get visibility over [IPs utilization](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/ips-utilization/).

### Regional Services

If you are using [Regional Services](https://developers.cloudflare.com/data-localization/regional-services/), you should take this into consideration when allocating dedicated IPv4 addresses. Traffic will egress from the specified locations as long as you have Dedicated CDN Egress IPs provisioned in those locations.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/configuration/dedicated-egress-ips/","name":"Dedicated CDN Egress IPs"}},{"@type":"ListItem","position":5,"item":{"@id":"/smart-shield/configuration/dedicated-egress-ips/how-it-works/","name":"How it works"}},{"@type":"ListItem","position":6,"item":{"@id":"/smart-shield/configuration/dedicated-egress-ips/how-it-works/egress-ips/","name":"Egress IPs"}}]}
```

---

---
title: IPs utilization
description: Monitor dedicated egress IP capacity and concurrent connections with GraphQL.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# IPs utilization

Use the [GraphQL API](https://developers.cloudflare.com/analytics/graphql-api/) to get aggregate data and monitor your dedicated IPs capacity (formerly known as Aegis).

Each Dedicated CDN Egress IP can support 40,000 concurrent connections per origin IP port. For example, if you have one dedicated IP and two origins (A and B), this single IP can support 40,000 concurrent connections to origin A, while simultaneously supporting 40,000 concurrent connections to origin B.

Refer to the [GraphQL Analytics API documentation](https://developers.cloudflare.com/analytics/graphql-api/getting-started/) for further guidance, or consider the [example](#example) below for a quickstart.

## GraphQL schema

The specific schema to get Dedicated CDN Egress IPs data is called `aegisIpUtilizationAdaptiveGroups`.

You can get average (`avg`) or maximum (`max`) utilization values (in percentage), and use the following dimensions:

* `datetimeFiveMinutes` ` time `  
   * Timestamp truncated to five minutes. For example, `2025-01-10T00:05:00Z`.
* `popName` ` string `  
   * The Cloudflare point of presence (PoP). For example, `sjc`.
* `egressIp` ` string `  
   * Your assigned Dedicated CDN Egress IP. For example, `192.0.2.1`.
* `origin` ` string `  
   * Origin IP and port. For example, `203.0.113.150:443`.
* `popUtilizationKey` ` string `  
   * The Cloudflare point of presence (PoP), the Dedicated CDN Egress IP, and the origin IP and port. For example, `sjc 192.0.2.1 203.0.113.150:443`.

## Example

Refer to the query below to learn how to get average utilization and maximum utilization by point of presence, and filter the results.

You can also select the button at the bottom to use this query for your account via the [Cloudflare GraphQL API Explorer ↗](https://graphql.cloudflare.com/explorer). Make sure to provide your account ID and timestamps, and replace the placeholders for `popName`, `egressIp`, and `origin` as needed.

```

query AegisIpUtilizationQuery(

  $accountTag: string

  $datetimeStart: string

  $datetimeEnd: string

) {

  viewer {

    utilization: accounts(filter: { accountTag: $accountTag }) {

      avgByPopUtilization: aegisIpUtilizationAdaptiveGroups(

        limit: 100

        filter: {

          datetimeFiveMinutes_geq: $datetimeStart

          datetimeFiveMinutes_leq: $datetimeEnd

        }

        orderBy: [datetimeFiveMinutes_ASC]

      ) {

        avg {

          utilization

        }

        dimensions {

          datetimeFiveMinutes

          popUtilizationKey

        }

      }


      maxByPopUtilization: aegisIpUtilizationAdaptiveGroups(

        limit: 100

        filter: {

          datetimeFiveMinutes_geq: $datetimeStart

          datetimeFiveMinutes_leq: $datetimeEnd

        }

        orderBy: [datetimeFiveMinutes_ASC]

      ) {

        max {

          utilization

        }

        dimensions {

          datetimeFiveMinutes

          popUtilizationKey

        }

      }


      filterPopUtilization: aegisIpUtilizationAdaptiveGroups(

        limit: 100

        filter: {

          datetimeFiveMinutes_geq: $datetimeStart

          datetimeFiveMinutes_leq: $datetimeEnd

          popName: "<CLOUDFLARE_POP>"

        }

        orderBy: [datetimeFiveMinutes_ASC]

      ) {

        max {

          utilization

        }

        dimensions {

          datetimeFiveMinutes

          popUtilizationKey

        }

      }


      filterIPUtilization: aegisIpUtilizationAdaptiveGroups(

        limit: 100

        filter: {

          datetimeFiveMinutes_geq: $datetimeStart

          datetimeFiveMinutes_leq: $datetimeEnd

          egressIp: "<YOUR_EGRESS_IP>"

        }

        orderBy: [datetimeFiveMinutes_ASC]

      ) {

        max {

          utilization

        }

        dimensions {

          datetimeFiveMinutes

          popUtilizationKey

        }

      }


      filterOriginUtilization: aegisIpUtilizationAdaptiveGroups(

        limit: 100

        filter: {

          datetimeFiveMinutes_geq: $datetimeStart

          datetimeFiveMinutes_leq: $datetimeEnd

          origin: "<ORIGIN_IP_AND_PORT>"

        }

        orderBy: [datetimeFiveMinutes_ASC]

      ) {

        max {

          utilization

        }

        dimensions {

          datetimeFiveMinutes

          popUtilizationKey

        }

      }

    }

  }

}


```

[Run in GraphQL API Explorer](https://graphql.cloudflare.com/explorer?query=I4VwpgTgngBAgmA5gSwM4EkAOBVALsgG2QC8BDfAewDsBFcaACgCgYYASUgY04pCtwAqpRAC4YqXBGRVELdgBNyYfAFswAZVykIuMRKky5bRbmXI1AUSry9k6bICUMAN5yAbsjAB3SC7msQfCIySioxLh4+XFQGADNCUwgxZxgI3n4hUXY0qMyYAF8nV1YS1LdEACEoAAUKHCCScmRqcKQ0LDxCRtC4RUx8NzAAcQheTBj-UpgiFWRdGABGAAYlydL4gkTktamTMzUAMWRBgFlpQLBUAH1EMGAxYyVVDS0dHdK956PT89NrgjuD0+5jAVnk7wKEIoEHkkCqYgA2sDDscwGcqBdrnB1ABhAC6OyKENI5T8UymgS6IWaVAh+Qh8hBVFQNNQZPJJWRYG+aN+lwhrEwdU6wSa1AA0mAoHSdvSdipSAAPKq1epUsVhVJtDBq0U9PoDYajEDjZgc6bmOZiZarc0bLbs81cnnozE3QEKJ4gzTaXACmDO1Guv5XAH3T2mZ5gmXm6GwiDwmBIr0on4YkPY-GEx1TBWKnPkyl6mkxjmMtTM1kF3Yp7lBvmof1C3XdGmS6Xm+nkuXk+2QVUi1stLUoHWD6nUXqkfqokZjCbmmZWxYrCF9pLVj61l0N93hx6R72vP3m1iBtNusNA2vR08wZsAOVIajEACIADw4gAyAHlsAARA4vzgAAlCwrmqH9qgAPlfUtyTjOEoERc9eXTS4rkzAlySJc0803EoiyHWlOwZJkWWoNlilPVDg35O9m3HDV23gkoeymdd0GqJjQlaUcOgaCcqCnGdBjnE0Fw5Jd5htNcEkgbY71o3dbn3LkfTeJTt3rdD-g9A99lBax-SQCBLh1N93wATT-ECrgsIYwPUdQri42DWNKRCE2QpNlN0zDcWwqZcI5fDqPNIihI8zlyKrcKy20i8-ibYVBOYqVovY9Z5IgH8pBQKgeJpPj2hbISRMNcTTQhaTrVXO0csUmjErQt1VOvQ81A0k9ms6uskowq8I0M29T2hZACssn8QPQIZ0AfVzqkwh9-wg6aBHc0jYxhJCUJauisUC7N4tKML-UijVorPWLKIIs99obFKyvSjsOS7KZ3tYd76XyIA&variables=N4IghgxhD2CuB2AXAKmA5iAXCAggYTwHkBVAOWQH0BJAERABoQATMRAU0QEsBbNgZURgAToiwgASgFEACgBl8kigHUqyABIU+ycVVIBxBs1YcebSfCZipchctUatO-SAC+QA)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/configuration/dedicated-egress-ips/","name":"Dedicated CDN Egress IPs"}},{"@type":"ListItem","position":5,"item":{"@id":"/smart-shield/configuration/dedicated-egress-ips/ips-utilization/","name":"IPs utilization"}}]}
```

---

---
title: Use with other Cloudflare products
description: Combine Dedicated CDN Egress IPs with Access, CNI, Spectrum, and Workers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Use with other Cloudflare products

Use Dedicated CDN Egress IPs in combination with different Cloudflare products.

## Access and CNI

You can use Dedicated CDN Egress IPs combined with [Cloudflare Network Interconnect (CNI)](https://developers.cloudflare.com/network-interconnect/) to secure your applications with [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/access-controls/policies/) without installing software or customizing code on your server.

While Access allows you to enforce policies at the hostname level, other solutions are usually necessary to protect against origin IP bypass [1](#user-content-fn-1). With Dedicated CDN Egress IPs, you only allow a small number of IPs (that are not publicly listed) through your network firewall and, with Cloudflare Network Interconnect, you can use a completely private path between Cloudflare and your application server, without exposure to the public Internet. For details and background, refer to the [Cloudflare blog ↗](https://blog.cloudflare.com/access-aegis-cni).

Dedicated CDN Egress IPs are included within [BGP advertisement over CNI](https://developers.cloudflare.com/network-interconnect/).

## Data Localization Suite

[Data Localization Suite (DLS)](https://developers.cloudflare.com/data-localization/) is an enterprise add-on that enables you to choose the location where Cloudflare encrypts, decrypts, and stores data.

To ensure egress will happen from DLS-specified locations, make sure you have Dedicated CDN Egress IPs provisioned in those locations. Refer to [IPs allocation](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/how-it-works/egress-ips/#ips-allocation) for details.

## Load Balancing

[Cloudflare Load Balancing](https://developers.cloudflare.com/load-balancing/) allows you to intelligently distribute traffic across your origins by issuing regular monitors (that assess origin health) and following the traffic steering policies you define.

By default, the Load Balancing monitors will use public Cloudflare IP addresses.

To avoid inconsistencies between what the Load Balancing monitors report and what you observe in service traffic with Dedicated CDN Egress IPs, make sure to turn on the **Simulate Zone** option in the [monitor settings](https://developers.cloudflare.com/load-balancing/monitors/create-monitor/#create-a-monitor).

## Spectrum

[Spectrum](https://developers.cloudflare.com/spectrum/) allows you to route email, file transfer, games, and more over TCP or UDP through Cloudflare. This means you can mask your origin and protect it from DDoS attacks.

While you can use [BYOIP](https://developers.cloudflare.com/byoip/) or static IPs to control which IPs are used for ingress with Spectrum, Dedicated CDN Egress IPs allows you to have a more strict list of [egress IPs](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/how-it-works/egress-ips/) as well.

Dedicated CDN Egress IPs with Spectrum supports both TCP and UDP application types. HTTP/HTTPS types are also supported, although through a different configuration.

If you are interested in any of these solutions, contact your account team.

## Workers

[Workers](https://developers.cloudflare.com/workers/) provides a serverless execution environment for you to create applications leveraging Cloudflare's global network.

Refer to the sections below for information on how Dedicated CDN Egress IPs pair up with Workers.

### `fetch`

[fetch() requests](https://developers.cloudflare.com/workers/runtime-apis/fetch/) that access services on your origin will use Dedicated CDN Egress IP addresses.

Workers subrequests — requests from one Worker to another — are expected to use different IPs. However, [fetch() requests](https://developers.cloudflare.com/workers/runtime-apis/fetch/) to external origins made by a Worker invoked via a subrequest will use Dedicated CDN Egress IP addresses.

### `connect`

For [connect() requests](https://developers.cloudflare.com/workers/runtime-apis/tcp-sockets/) \- which create outbound TCP connections from Workers - Dedicated CDN Egress IPs are **not** used.

## Footnotes

1. When an attacker knows your origin server IP and uses it to directly interact with the target application. [↩](#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":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/configuration/dedicated-egress-ips/","name":"Dedicated CDN Egress IPs"}},{"@type":"ListItem","position":5,"item":{"@id":"/smart-shield/configuration/dedicated-egress-ips/other-products/","name":"Use with other Cloudflare products"}}]}
```

---

---
title: Setup
description: Configure Dedicated CDN Egress IPs using the Cloudflare API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Setup

You can use the [Edit Zone Settings API endpoint](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) to set up Dedicated CDN Egress IPs (formerly known as Aegis). If you are not familiar with how Cloudflare API works, refer to [Fundamentals](https://developers.cloudflare.com/fundamentals/api/).

Enterprise-only

Dedicated CDN Egress IPs (DCEI) are currently available to Enterprise customers. Contact your account team to request access.

## Requirements

* The Dedicated CDN Egress IPs (DCEI) zone setting is only available within Cloudflare accounts that own leased IPs, or accounts to which a [BYOIP prefix](https://developers.cloudflare.com/byoip/) has been delegated. If you wish to use Dedicated CDN Egress IPs for zones that do not meet this criteria, contact your account team.
* Each dedicated egress pool can consist of either IPs from a [BYOIP prefix](https://developers.cloudflare.com/byoip/) or Cloudflare-leased IPs. A single dedicated egress pool cannot contain both BYOIPs and leased IPs. Also, a single BYOIP prefix can be used for either CDN ingress or CDN egress, but not both.

Warning

You must allowlist the IP addresses from this pool in your infrastructure before linking it to a zone. If you skip this step, traffic will not reach your origin, causing errors.

## Turn on DCEI for a zone

1. Contact your account team to get the ID for your dedicated egress pool.
2. Make a `PATCH` request to the [Edit Zone Setting](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) endpoint:
* Specify `aegis` as the setting ID in the URL.
* In the request body, set `enabled` to `true` and use the ID from the previous step as the `pool_id` value.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`

Edit zone setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/aegis" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "id": "aegis",

    "value": {

        "enabled": true,

        "pool_id": "<EGRESS_POOL_ID>"

    }

  }'


```

## Check DCEI status for a zone

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`
* `Zone Settings Read`

Get zone setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/aegis" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

## Turn off DCEI for a zone

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`

Edit zone setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/aegis" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "id": "aegis",

    "value": {

        "enabled": false

    }

  }'


```

## Check your IPs

You can find your leased dedicated IPs for CDN egress on the dashboard under [**Address space** \> **Leased IPs** ↗](https://dash.cloudflare.com/?to=/:account/ip-addresses/address-space).

If you are using BYOIP, refer to **BYOIP prefixes** instead.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/configuration/dedicated-egress-ips/","name":"Dedicated CDN Egress IPs"}},{"@type":"ListItem","position":5,"item":{"@id":"/smart-shield/configuration/dedicated-egress-ips/setup/","name":"Setup"}}]}
```

---

---
title: Health Checks analytics
description: Use Health Checks analytics to debug origin availability issues.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Health Checks analytics

Use Health Checks analytics to debug possible origin issues.

You can evaluate origin uptime, latency, failure reason, and specific event logs:

* **Health Checks By Uptime**: Shows the percentage of uptime for individual origins over time.
* **Health Checks By Failure Reason**: Shows a breakdown of failures by the specific reason. Refer to [common error code causes and solutions below](#common-error-codes).
* **Health Checks By Latency**: Shows average latency – measured in round trip time — for individual origins over time.
* **Event Log**: Shows individual health check data.  
   * Select each record for additional details on **Round trip time**, the **Failure Reason**, the **Average Waterfall** (showing chronological data about request stages), **Response status code**, and more.  
   * Note that **Global** is not a configured region; it represents the aggregated data from all enabled regions.

## Common error codes

### TCP connection failed

#### Cause

Health Checks failed to establish a TCP connection to your origin server.

#### Solution

This typically occurs when there is a network failure between Cloudflare and your origin, and/or a firewall refuses to allow our connection. Ensure your network and firewall configurations are not interfering with traffic.

### HTTP timeout occurred

#### Cause

The origin failed to return an HTTP response within the timeout configured. This happens if you have the timeout set to a low number. For example, one to two seconds.

#### Solution

Cloudflare recommends increasing the HTTP response timeout to allow the origin server to respond.

### Response code mismatch error

#### Cause

Cloudflare receives an HTTP status code that does not match the values defined in the `expected_codes` property of your Health Check configuration.

#### Solution

Response codes must match the `expected_codes`. Confirm the values are correct by comparing the expected response codes and the status code received in the Event Log.

#### ​​Alternate cause

You may also see this issue if you have a Health Check configured to use HTTP connections and your origin server is redirecting to HTTPS. In this case, the response code will often be `301`, `302`, or `303`.

#### Solution

Change your Cloudflare Health Check configuration to use HTTPS or set the value of `follow_redirect` to `true` so that Cloudflare can resolve the correct status code.

### Response body mismatch error

#### Cause

The response body returns from your origin server and does not include the (case-insensitive) value of `expected_body` configured in your Health Check.

Note

We only read the first 10 KB of the response. If you return a larger response, and the `expected_body` is not in the first 10 KB, the Health Check will fail.

#### Solution

Ensure the `expected_body` is in the first 10 KB of the response body. ​​

### TLS untrusted certificate error

#### Cause

The certificate is not trusted by a public Certificate Authority (CA).

#### Solution

If you’re using a self-signed certificate, Cloudflare recommends either using a publicly trusted certificate or setting the `allow_insecure` property on your Health Check to `true`.

### TLS name mismatch error

#### Cause

Our Health Check (client) was not able to match a name on the server certificate to the hostname of the request.

#### Solution

Inspect your Health Check configuration to confirm that the `header` value set in the Cloudflare Health Check is correct.

### TLS protocol error

#### Cause

This error can occur if you are using an older version of TLS or your origin server is not configured for HTTPS.

#### Solution

Ensure that your origin server supports TLS 1.2 or greater and is configured for HTTPS.

### TLS unrecognized name error

#### Cause

The server did not recognize the name provided by the client. When a host header is set, this is set as the ServerName in the initial TLS handshake. If it is not set, Cloudflare will not provide a ServerName, which can cause this error.

#### Solution

Set the host header in your Health Check object.

### ​​No route to host error

#### Cause

The IP address cannot be reached from Cloudflare’s network. Common causes are ISP or hosting provider network issues (e.g. BGP level), or that the IP does not exist.

#### Solution

Ensure IP is accurate, and check if there is an ISP or hosting provider network issue.

### TCP Timeout

#### Cause

Data transmission was not acknowledged and the retransmit of data did not succeed.

#### Solution

Confirm whether the SYN-ACK for the handshake takes place at your origin and contact [Cloudflare support](https://developers.cloudflare.com/support/contacting-cloudflare-support/).

### ​​Network Unreachable

#### Cause

Cloudflare cannot connect to the origin web server due to network unavailability. This is usually caused by a network issue or incorrect origin IP.

#### Solution

Check the IP entered for the origin in Cloudflare’s Health Checks configuration or the IP returned via DNS for the origin hostname.

### HTTP Invalid Response

#### Cause

Usually caused by an HTTP 502 error or bad gateway.

#### Solution

Ensure the origin web server responds to requests and that no applications have crashed or are under high load.

### DNS Unknown Host

#### Cause

The origin web server hostname does not exist.

#### Solution

Confirm the origin web server resolves to an IP address.

### Connection Reset by Peer

#### Cause

A network error occurred while the client received data from the origin web server.

#### Solution

Confirm whether the origin web server is experiencing a high amount of traffic or an error.

### Monitor Configuration Error

#### Cause

There was a configuration error in the Health Check and no checks were run against the origin.

#### Solution

Review your Health Check configuration to ensure it matches an expected request to your origin.

### ​​DNS Internal

#### Cause

The origin web server’s hostname resolves to an internal or restricted address. No checks are run against this origin.

#### Solution

Cloudflare does not allow use of an origin web server hostname that resolves to a Cloudflare IP.

### Other Failure

#### Cause

If the failure cannot be classified as any other type of failure mentioned above.

#### Solution

Contact [Cloudflare support](https://developers.cloudflare.com/support/contacting-cloudflare-support/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/configuration/health-checks/","name":"Health Checks"}},{"@type":"ListItem","position":5,"item":{"@id":"/smart-shield/configuration/health-checks/analytics/","name":"Health Checks analytics"}}]}
```

---

---
title: Manage Health Checks
description: Create, configure, and manage health checks for your origin servers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Manage Health Checks

Refer to the section below to learn how to manage your Smart Shield health checks.

## Create and edit health checks

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com) and select your account and domain.
2. Go to **Speed** \> **Smart Shield**.
3. For Health Checks, select **Manage**.
4. Select **Create** or find an existing health check and select **Edit**.
5. Fill out the form or edit existing values, paying special attention to:  
   * The values for **Interval** and **Check regions**, because decreasing the **Interval** and increasing **Check regions** may increase the load on your origin server.  
   * **Retries**, which specify the number of retries to attempt in case of a timeout before marking the origin as unhealthy.
6. Select **Save and Deploy**.

## Configure alerts

You can configure [notification emails](https://developers.cloudflare.com/notifications/get-started/) to be alerted when the health check detects that there is a change in the status of your origin server. Cloudflare will send you an email within seconds so you can take the necessary action before customers are impacted.

The email provides information to determine what caused the health status change. You can evaluate when the change happened, the status of the origin server, if and why it is unhealthy, the expected response code, and the received response code. Refer to [common error codes](https://developers.cloudflare.com/smart-shield/configuration/health-checks/analytics/#common-error-codes) for further guidance.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com) and select your account and domain.
2. Go to **Speed** \> **Smart Shield**.
3. For Health Checks, select **Manage** and then **Configure an alert**.
4. Fill out the **Notification name** and **Description**.
5. Add a Notification email.
6. Select **Next**.
7. Add health checks to include in your alerts.
8. Choose the **Notification trigger**, which determines when you receive alerts.
9. Select **Create**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/configuration/health-checks/","name":"Health Checks"}},{"@type":"ListItem","position":5,"item":{"@id":"/smart-shield/configuration/health-checks/setup/","name":"Manage Health Checks"}}]}
```

---

---
title: Zone Lockdown
description: Migrate from Zone Lockdown to WAF custom rules for IP-based access control.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Zone Lockdown

Currently, any Cloudflare customer on a paid plan can configure Health Checks against any host or IP. [Zone Lockdown](https://developers.cloudflare.com/waf/tools/zone-lockdown/) specifies a list of one or more IP addresses, CIDR ranges, or networks that are the only IPs allowed to access a domain, subdomain, or URL. It allows multiple destinations in a single rule as well as IPv4 and IPv6 addresses. IP addresses not specified in the Zone Lockdown rule are denied access to the specified resources.

Customers who use zone lockdown and want their health checks to continue passing can use [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/create-dashboard/) to bypass zone lockdown.

## Bypass zone lockdown

To bypass zone lockdown using a WAF custom rule:

1. Follow the steps to [create a custom rule in the dashboard](https://developers.cloudflare.com/waf/custom-rules/create-dashboard/).
2. Create a custom rule matching on **user agent**.  
Cloudflare Health Checks have a user agent of the following format:`Mozilla/5.0 (compatible;Cloudflare-Healthchecks/1.0;+https://www.cloudflare.com/; healthcheck-id: XXX)` where `XXX` is replaced with the first 16 characters of the Health Check ID.  
To allow a specific Health Check, verify if the user agent contains the first 16 characters of the Health Check ID.
3. Set the action to _Skip_ and the corresponding feature to **Zone Lockdown** under **More components to skip**.

### Via the API

This example adds a new WAF custom rule to the ruleset with ID `{ruleset_id}` that skips zone lockdown for incoming requests with a user agent containing `1234567890abcdef`:

Terminal window

```

curl "https://api.cloudflare.com/client/v4/{zone_id}/rulesets/{ruleset_id}/rules" \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "action": "skip",

  "action_parameters": {

    "products": [

      "zoneLockdown"

    ]

  },

  "expression": "http.user_agent contains \"1234567890abcdef\"",

  "description": "bypass zone lockdown - specific healthcheck"

}'


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/configuration/health-checks/","name":"Health Checks"}},{"@type":"ListItem","position":5,"item":{"@id":"/smart-shield/configuration/health-checks/zone-lockdown/","name":"Zone Lockdown"}}]}
```

---

---
title: Regional Tiered Cache
description: Limit upper-tier data centers to your preferred region for data locality.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Regional Tiered Cache

Availability

Included with Enterprise plans. Available to Free, Pro, and Business plans through Smart Shield Advanced.

Regional Tiered Cache provides an additional layer of caching for customers who have a global traffic footprint and want to serve content faster by avoiding network latency when there is a cache `MISS` in a lower-tier, resulting in an upper-tier fetch in a data center located far away.

Regional Tiered Cache instructs Cloudflare to check a regional hub data center near the lower tier before going to the upper tier that may be outside of the region.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/configuration/regional-tiered-cache/","name":"Regional Tiered Cache"}}]}
```

---

---
title: Smart Tiered Cache
description: Reduce origin requests by serving cached content from upper-tier data centers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Smart Tiered Cache

Availability

Available in all Smart Shield packages.

With data centers around the world, Cloudflare caches content very close to end users. However, if a piece of content is not in cache, the Cloudflare data centers must contact the origin server to receive the cacheable content. Tiered cache works by dividing Cloudflare's data centers into a hierarchy of lower-tiers and upper-tiers, where only upper-tiers can ask your origin for content.

Smart Tiered Cache dynamically selects the single closest upper tier for each of your website’s origins with no configuration required, using our in-house performance and routing data. Cloudflare collects latency data for each request to an origin, and uses the latency data to determine how well any upper-tier data center is connected with an origin. As a result, Cloudflare can select the data center with the lowest latency to be the upper-tier for an origin.

#### Public cloud origins

Origins hosted on public cloud providers (AWS, GCP, Azure, or Oracle Cloud) often use [anycast ↗](https://www.cloudflare.com/en-gb/learning/cdn/glossary/anycast-network/) or regional unicast networking, which prevents Smart Tiered Cache from determining the origin location through latency probing alone. To solve this, you can set a **cloud region hint** that tells Smart Tiered Cache which cloud provider and region your origin is in. Smart Tiered Cache then selects a primary upper-tier data center close to that cloud region, plus a fallback in a different location for resilience. To set up a cloud region hint, refer to [Set a cloud region hint](https://developers.cloudflare.com/cache/how-to/tiered-cache/#set-a-cloud-region-hint).

#### Load Balancing interaction

While Smart Tiered Cache selects one Upper Tier per origin, when using Load Balancing, Smart Tiered Cache will select the single best Upper Tier for the entire [Load Balancing Pool](https://developers.cloudflare.com/load-balancing/understand-basics/load-balancing-components/#pools).

#### Caveats

You need to be careful when updating your origin IPs/DNS records while Smart Tiered Cache is enabled. Depending on the changes made, it may cause the existing assigned upper tiers to change, resulting in an increased `MISS` rate as cache is refilled in the new upper tiers. If the origin is switched to a network behind anycast, it will significantly reduce the effectiveness of Smart Tiered Cache unless you set a [cloud region hint](https://developers.cloudflare.com/cache/how-to/tiered-cache/#set-a-cloud-region-hint).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/smart-shield/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/smart-shield/configuration/smart-tiered-cache/","name":"Smart Tiered Cache"}}]}
```

---

---
title: Cloudflare Spectrum
description: Proxy and protect TCP and UDP applications with Cloudflare Spectrum.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare Spectrum

Spectrum provides security and acceleration for any [TCP ↗](https://www.cloudflare.com/learning/ddos/glossary/tcp-ip/) or [UDP ↗](https://www.cloudflare.com/learning/ddos/glossary/user-datagram-protocol-udp/) based application.

 Available on Paid plans 

Spectrum allows you to route MQTT, email, file transfer, version control, games, and more over TCP or UDP through Cloudflare to mask the origin and protect it from [DDoS attacks ↗](https://www.cloudflare.com/learning/ddos/what-is-a-ddos-attack/).

Note

Custom TCP/UDP applications require an Enterprise plan with Spectrum as a paid add-on. See [Protocols per plan](https://developers.cloudflare.com/spectrum/protocols-per-plan/) for details, or contact your account team to enable.

---

## Features

###  Enable Proxy protocol 

Use a proxy protocol for Cloudflare to pass on the client IP to your service.

[ Use Enable Proxy protocol ](https://developers.cloudflare.com/spectrum/how-to/enable-proxy-protocol/) 

###  DDoS Protection for Spectrum 

Learn more about what L3/4 DDoS Protection is included as part of the Spectrum service.

[ Use DDoS Protection for Spectrum ](https://developers.cloudflare.com/spectrum/about/ddos-for-spectrum/) 

---

## Related products

**[DDoS Protection](https://developers.cloudflare.com/ddos-protection/)** 

Cloudflare DDoS protection secures websites, applications, and entire networks while ensuring the performance of legitimate traffic is not compromised.

**[BYOIP](https://developers.cloudflare.com/byoip/)** 

Get Cloudflare's security and performance while using your own IPs. With Bring Your Own IP (BYOIP), Cloudflare announces your IPs in all our locations.

**[Load Balancing](https://developers.cloudflare.com/load-balancing/)** 

Cloudflare Load Balancing distributes traffic across your endpoints, which reduces endpoint strain and latency and improves the experience for end users.

**[DNS](https://developers.cloudflare.com/dns/)** 

Cloudflare's global DNS platform provides speed and resilience. DNS customers also benefit from free DNSSEC, and protection against route leaks and hijacking.

---

## More resources

[Plans](https://www.cloudflare.com/plans/) 

Compare available Cloudflare plans.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}}]}
```

---

---
title: Protocols per plan
description: Supported protocols for Spectrum applications by Cloudflare plan.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Protocols per plan

On this table, you have information about which protocols are available per plan.

| Free                        | Pro | Business    | Enterprise  |             |
| --------------------------- | --- | ----------- | ----------- | ----------- |
| Availability                | No  | Paid add-on | Paid add-on | Yes         |
| TCP                         | No  | No          | No          | Paid add-on |
| UDP                         | No  | No          | No          | Paid add-on |
| HTTP                        | No  | No          | No          | Paid add-on |
| HTTPS                       | No  | No          | No          | Paid add-on |
| Minecraft (one app allowed) | No  | Yes         | Yes         | Yes         |
| SSH (one app allowed)       | No  | Yes         | Yes         | Yes         |
| RDP (one app allowed)       | No  | No          | Yes         | Yes         |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/protocols-per-plan/","name":"Protocols per plan"}}]}
```

---

---
title: Get started
description: Create a Spectrum application to proxy TCP or UDP traffic through Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

Spectrum is available on all paid plans. Pro and Business support selected protocols only, whereas Enterprise supports all TCP and UDP based traffic. Refer to [Configuration options](https://developers.cloudflare.com/spectrum/reference/configuration-options/) for more configuration details.

To create a Spectrum application, you can either use an IP address, a CNAME Record or a load balancer. Independently of the method you use, you can create the application through the dashboard or via [API](https://developers.cloudflare.com/api/resources/spectrum/subresources/apps/methods/list/).

Certain fields in Spectrum request and response bodies require an Enterprise plan. Refer to the [Settings by plan](https://developers.cloudflare.com/spectrum/reference/settings-by-plan/) page for more details.

## Create a Spectrum application using an IP address

To create a Spectrum application using an IP address, Cloudflare normally assigns you an arbitrary IP from Cloudflare’s IP pool to your application. If you want to use your own IP addresses, you can use [BYOIP](https://developers.cloudflare.com/spectrum/about/byoip/) or you can also use a [Static IP](https://developers.cloudflare.com/spectrum/about/static-ip/). In these two last cases, you need to create your Spectrum application through the API, as these features are not available via dash. When using the API, the field `origin_direct` takes as input the IP address.

Add your application via Dashboard

1. In the Cloudflare dashboard, go to the **Spectrum** page.  
[ Go to **Spectrum** ](https://dash.cloudflare.com/?to=/:account/:zone/spectrum)
2. Select **Create an Application**. If this is your first time using Spectrum, the **Create an Application** modal appears.
3. Select your **Application Type**.
4. Under **Domain**, enter the domain that will use Spectrum.
5. Under **Edge Port**, enter the port Cloudflare should use for your application.
6. Under **Origin**, enter your application's origin IP and port.
7. If your application requires the client IP and supports [Proxy Protocol ↗](https://www.haproxy.com/blog/haproxy/proxy-protocol/), enable **Proxy Protocols**. Proxy Protocol is a method for a proxy like Cloudflare to send the client IP to the origin application.
8. Select **Add**.

Add your application via API

Below is a curl example and the associated data being posted to the API.

**API example:**

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`

Create Spectrum application using a name for the origin

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/spectrum/apps" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "protocol": "tcp/22",

    "dns": {

        "type": "CNAME",

        "name": "ssh.example.com"

    },

    "origin_direct": [

        "tcp://192.0.2.1:22"

    ],

    "proxy_protocol": "off",

    "ip_firewall": true,

    "tls": "full",

    "edge_ips": {

        "type": "dynamic",

        "connectivity": "all"

    },

    "traffic_type": "direct",

    "argo_smart_routing": true

  }'


```

**Example data:**

```

{

  "success": true,

  "errors": [],

  "messages": [],

  "result": {

    "id": "ea95132c15732412d22c1476fa83f27a",

    "protocol": "tcp/22",

    "dns": {

      "type": "CNAME",

      "name": "ssh.example.com"

    },

    "origin_direct": ["tcp://192.0.2.1:22"],

    "proxy_protocol": "off",

    "ip_firewall": true,

    "tls": "full",

    "edge_ips": {

      "type": "dynamic",

      "connectivity": "all"

    },

    "traffic_type": "direct",

    "argo_smart_routing": true,

    "created_on": "2014-01-02T02:20:00Z",

    "modified_on": "2014-01-02T02:20:00Z"

  }

}


```

## Create a Spectrum application using a CNAME record

To create a Spectrum application using a CNAME record, you will need to create a [CNAME record ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-cname-record/) on your Cloudflare hosted zone that points to your origin's hostname. This is required to resolve to your hostname origin. Refer to [Create DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records), for more information. When using a CNAME as an origin, note that Cloudflare needs to be authoritative for that zone. When using the API, the `origin_dns` field takes as input the CNAME record.

Add your application via Dashboard

1. In the Cloudflare dashboard, go to the **Spectrum** page.  
[ Go to **Spectrum** ](https://dash.cloudflare.com/?to=/:account/:zone/spectrum)
2. Select **Create an Application**. If this is your first time using Spectrum, the **Create an Application** modal appears.
3. Select your **Application Type**.
4. Under **Domain**, enter the domain that will use Spectrum.
5. Under **Edge Port**, enter the port Cloudflare should use for your application.
6. Under **Origin**, enter your `CNAME` record name.
7. Select **Add**.

Add your application via API

Below is a curl example and the associated data being posted to the API.

**API example:**

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`

Create Spectrum application using a name for the origin

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/spectrum/apps" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "dns": {

        "type": "CNAME",

        "name": "spectrum-cname.example.com"

    },

    "ip_firewall": false,

    "protocol": "tcp/22",

    "proxy_protocol": "off",

    "tls": "off",

    "origin_dns": {

        "name": "cname-to-origin.example.com",

        "ttl": 1200

    },

    "origin_port": 22

  }'


```

**Example data:**

```

{

  "dns": {

    "type": "CNAME",

    "name": "spectrum-cname.example.com"

  },

  "ip_firewall": false,

  "protocol": "tcp/22",

  "proxy_protocol": "off",

  "tls": "off",

  "origin_dns": {

    "name": "cname-to-origin.example.com",

    "ttl": 1200

  },

  "origin_port": 22

}


```

## Create a Spectrum application using a load balancer

To create a Spectrum application using a load balancer, you will need to generate a load balancer from the dashboard or via the API. Refer to the [Load Balancing documentation](https://developers.cloudflare.com/load-balancing/additional-options/spectrum/#1-configure-your-load-balancer) for more details.

Note

To prevent issues with DNS resolution for a Spectrum application, do not use the same Spectrum hostname as a current Load Balancing hostname.

Add your application via Dashboard

1. In the Cloudflare dashboard, go to the **Spectrum** page.  
[ Go to **Spectrum** ](https://dash.cloudflare.com/?to=/:account/:zone/spectrum)
2. Select **Create an Application**. If this is your first time using Spectrum, the **Create an Application** modal appears.
3. Select your **[Application Type](https://developers.cloudflare.com/spectrum/reference/configuration-options/#application-type)**.
4. Under **Domain**, enter the domain that will use Spectrum.
5. Under **Edge Port**, enter the port Cloudflare should use for your application.
6. Under **Origin**, select **Load Balancer**.
7. Select the load balancer you want to use from the dropdown. Disabled load balancers will not show on the **Load Balancer** menu.
8. Select **Add**.

Add your application via API

Below is a curl example and the associated data being posted to the API.

**API example:**

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`

Create Spectrum application using a name for the origin

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/spectrum/apps" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "dns": {

        "type": "CNAME",

        "name": "spectrum-cname.example.com"

    },

    "ip_firewall": false,

    "protocol": "tcp/22",

    "proxy_protocol": "off",

    "tls": "off",

    "origin_dns": {

        "name": "cname-to-origin.example.com",

        "ttl": 1200

    },

    "origin_port": 22

  }'


```

**Example data:**

```

{

  "dns": {

    "type": "CNAME",

    "name": "spectrum-cname.example.com"

  },

  "ip_firewall": false,

  "protocol": "tcp/22",

  "proxy_protocol": "off",

  "tls": "off",

  "origin_dns": {

    "name": "cname-to-origin.example.com",

    "ttl": 1200

  },

  "origin_port": 22

}


```

## View traffic

You can now proxy traffic through Cloudflare without additional configuration. As you run traffic through Cloudflare, you will see the last minute of traffic from **Spectrum** in the dashboard.

If you have any feedback, please [let us know ↗](https://community.cloudflare.com/c/website-application-performance/spectrum/48).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/get-started/","name":"Get started"}}]}
```

---

---
title: Glossary
description: Definitions for terms used across Cloudflare Spectrum documentation.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Glossary

Review the definitions for terms used across Cloudflare's Spectrum documentation.

| Term                                               | Definition                                                                                                                                                                                        |
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ACK (Acknowledge)                                  | The final step in the TCP three-way handshake, confirming the establishment of a connection.                                                                                                      |
| FTP (File Transfer Protocol)                       | A standard network protocol used for transferring files from one host to another over a TCP-based network.                                                                                        |
| FTPS (File Transfer Protocol Secure)               | An extension of FTP that adds support for the Transport Layer Security (TLS) or Secure Sockets Layer (SSL) cryptographic protocols.                                                               |
| layer 3                                            | The network layer in the OSI model, responsible for logical addressing, routing, and forwarding of data between devices on different networks.                                                    |
| layer 4                                            | The transport layer in the OSI model, managing end-to-end communication, error-checking, and flow control.                                                                                        |
| MQTT (Message Queuing Telemetry Transport)         | A lightweight, publish-subscribe messaging protocol often used for communication in the Internet of Things (IoT) and other resource-constrained scenarios.                                        |
| OSI model (Open Systems Interconnection model)     | A conceptual framework that standardizes the functions of a telecommunication or computing system into seven abstraction layers.                                                                  |
| proxy protocol                                     | A protocol used by network proxies to convey client connection information to the destination server, facilitating proper handling of client requests.                                            |
| reverse proxy                                      | A server that handles requests on behalf of clients, forwarding them to backend servers and managing tasks like load balancing and security.                                                      |
| SFTP (Secure File Transfer Protocol)               | A secure file transfer protocol that uses the Secure Socket Shell (SSH) protocol for encryption and authentication.                                                                               |
| SMTP Server (Simple Mail Transfer Protocol Server) | A server responsible for sending, receiving, and relaying email messages over a network, following the SMTP protocol.                                                                             |
| SYN (Synchronize)                                  | The initial step in establishing a TCP connection, where a device requests a connection with another by sending a SYN packet.                                                                     |
| SYN-ACK (Synchronize-Acknowledge)                  | The second step in the TCP three-way handshake, where the server responds to a SYN request with a SYN-ACK packet.                                                                                 |
| TCP (Transmission Control Protocol)                | A connection-oriented protocol in the transport layer of the Internet Protocol Suite, providing reliable and ordered delivery of data between devices.                                            |
| UDP (User Datagram Protocol)                       | UDP (User Datagram Protocol) is a connectionless transport layer protocol that provides fast and lightweight data transmission between devices on a network, prioritizing speed over reliability. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/glossary/","name":"Glossary"}}]}
```

---

---
title: BYOIP
description: Use your own IP addresses with Spectrum applications.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# BYOIP

When creating a Spectrum application, Cloudflare normally assigns an arbitrary IP from Cloudflare’s IP pool to your application. If you want to be explicit in your network setup or use your own IP addresses, BYOIP with Spectrum allows you to do just that.

BYOIP stands for [Bring Your Own IP](https://developers.cloudflare.com/byoip/). If you own an IP prefix you can migrate it to Cloudflare. After migration, Cloudflare broadcasts your IP prefix and traffic is routed to the global Cloudflare network. However, without configuration, Cloudflare will not know how to handle this traffic. The last step is to add Spectrum applications for all applications that you wish to protect with the IP addresses you want associated with them.

Warning

When switching from non-BYOIP to BYOIP, if you are already using a Spectrum application, you need to delete your configurations and recreate new ones.

The smallest prefixes that Cloudflare currently supports is /24 for IPv4 and /48 for IPv6.

BYOIP does not come standard with Spectrum. To enable it, contact your account team.

UDP applications

Spectrum UDP applications are [not supported](https://developers.cloudflare.com/spectrum/reference/limitations/#udp) when using Spectrum with BYOIP.

## Assign an IP address

To use an IP, it must be assigned to a Spectrum app to create the appropriate A (IPv4) or AAAA (IPv6) records. This is done by specifying one or more IP addresses when creating an application through the API. Any change to the application's properties also needs to be done via API. In addition, you must update the DNS `"type"` field to `"ADDRESS"` to create a Spectrum app using BYOIP.

```

{

  "id": "4590376cf2994d72cee36828ec4eff19",

  "protocol": "tcp/22",

  "dns": {

    "type": "ADDRESS",

    "name": "ssh.example.com"

  },

  "origin_direct": ["tcp://192.0.2.1:22"],

  "ip_firewall": true,

  "proxy_protocol": false,

  "spp": false,

  "tls": "off",

  "traffic_type": "direct",

  "edge_ips": {

    "type": "static",

    "ips": ["198.51.100.10", "2001:DB8::1"]

  }

}


```

## Example

In the example below, the application routes traffic through Cloudflare’s HTTP pipeline, including WAF, Workers and CDN functionality.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`

Create Spectrum application using a name for the origin

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/spectrum/apps" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "protocol": "tcp/80",

    "dns": {

        "type": "ADDRESS",

        "name": "www.example.com"

    },

    "origin_direct": [

        "tcp://192.0.2.1:80"

    ],

    "tls": "off",

    "traffic_type": "http",

    "edge_ips": {

        "type": "static",

        "ips": [

            "198.51.100.10",

            "2001:DB8::1"

        ]

    }

  }'


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/about/","name":"About"}},{"@type":"ListItem","position":4,"item":{"@id":"/spectrum/about/byoip/","name":"BYOIP"}}]}
```

---

---
title: DDoS Protection for Spectrum
description: Layer 3 and 4 DDoS protection for TCP and UDP Spectrum applications.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DDoS Protection for Spectrum

Spectrum provides DDoS Protection at layers 3-4 of the [OSI model ↗](https://www.cloudflare.com/learning/ddos/glossary/open-systems-interconnection-model-osi/), that is against TCP and UDP based DDoS attacks.

Spectrum works as a layer 4 reverse proxy, therefore a proper TCP connection must be first established before traffic is proxied to the origin. This moves any impact of SYN or SYN-ACK reflection attacks to the Cloudflare global network. Additionally, by using Spectrum in front of your application, your origin IP is concealed — preventing attackers from targeting your origin server directly. It is also recommended that you replace your origin IP address after moving to Cloudflare, and lock it down to only accept traffic from [Cloudflare’s IP address range ↗](https://www.cloudflare.com/ips/).

Random or out-of-state TCP packets should not be passed to the origin if a legitimate TCP connection has not yet been established between the client and Cloudflare. Spectrum also [leverages SYN cookie challenges as part of the Linux networking stack ↗](https://blog.cloudflare.com/syn-packet-handling-in-the-wild/) to defend against floods.

Furthermore, if a flood of packets of an unspecified protocol target your application (for example, your Spectrum application is for TCP traffic, and a UDP flood targets your Spectrum application), the packets will be dropped. Similarly, if packets target a port or port range that you did not specify, they will also be dropped.

L3/4 DDoS attacks should be detected and mitigated by the [Network-layer DDoS Attack Protection managed ruleset](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/) that is enabled by default. This ruleset detects and mitigates DDoS attacks by dynamically fingerprinting attacks based on packet header fields.

For protecting HTTP/S applications against L7 DDoS attacks and to benefit from caching and additional features, onboard your application to Cloudflare’s Web Application Firewall/Content Delivery Network service, which works in tandem with Cloudflare Spectrum.

Refer to [Cloudflare DDoS Protection](https://developers.cloudflare.com/ddos-protection/) to learn more.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/about/","name":"About"}},{"@type":"ListItem","position":4,"item":{"@id":"/spectrum/about/ddos-for-spectrum/","name":"DDoS Protection for Spectrum"}}]}
```

---

---
title: FTP
description: Enable Spectrum for FTP services and understand protocol limitations.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# FTP

Enabling Spectrum for FTP is not straightforward due to the implementation of the protocol. This guide gives an overview of the intricacies of FTP and under which circumstances you can enable Spectrum for your FTP service.

Note

This feature requires an Enterprise plan. If you would like to upgrade, contact your account team.

## How FTP Operates

FTP leverages two different sockets, one for issuing commands and the other for actual data transfer. The control socket takes care of users logging in and sending commands, and the data socket is where directory listings and files actually get transferred.

There are two ways in which client and server can establish a data socket: active and passive. In active mode, the server connects _back_ to the client on a port that they have specified, which can create issues where clients are behind an NAT. The alternative is passive mode, where the server opens an extra port that the client then connects to. For an overview of active versus passive FTP, refer to [Active FTP vs. Passive FTP, a Definitive Explanation ↗](http://slacksite.com/other/ftp.html).

In passive mode, the FTP server communicates a port that the client should connect to, which is done on the control socket via a PASV command. By default, the FTP server responds with the IP address that it is listening on. This scenario is fine for servers running directly on a public-facing IP but creates issues when a server is behind an NAT, firewall, or Cloudflare Spectrum.

Alternatively, more modern FTP server software supports [FTP extensions ↗](https://tools.ietf.org/html/rfc2428), which introduces the EPSV command that omits the IP address that the client should connect on. Instead, the client connects to the same IP that it connected to for the control pane.

## What Does and Does Not Work

Spectrum is able to protect servers serving FTP traffic in _passive mode only_. Active mode is not supported due to the fact that the origin server sees the Spectrum IP as being the client instead of the actual client IP. When the client issues a PORT command with their own IP, the FTP server rejects because the two addresses do not match.

Passive mode in combination with EPSV works out of the box with no origin-side configuration required. Note that the client must also support EPSV for this to work. Traditional passive mode with PASV is possible with minimal origin-side configuration (see below, Protecting an FTP server with Spectrum)

## Protect an FTP Server with Spectrum

Configuring Spectrum to protect your FTP server requires creating a set of Spectrum applications that point to your origin and some configuration on the FTP server.

### Protect the Control Port

The control plane runs on port 21 by default, and there is nothing special that needs to be to protect this part of the FTP server. In the example below, replace 198.51.100.1 with the IP of the origin server.

![Add an application dialog with IP address and port set to 21](https://developers.cloudflare.com/_astro/ftp-control-plane-app.CCDNXmIO_Z1qUJ8V.webp) 

This configuration proxies incoming connections to the origin. However, if clients issue a PASV command, they will still receive the IP of the actual origin for the data connection. This is not preferred, as this exposes the origin's IP to the client instead of being masked behind Spectrum. Steps to prevent this are documented in sections below.

### Protect Data Ports

Most FTP servers allow configuration of the port range that the server will use to open data connections. It is recommended to specify a port range to prevent accidentally exposing other ports on the server. For each port in the range, create a corresponding Spectrum application that maps to that port.

Additionally, the FTP server needs to be configured to expose the correct IP when the client issues a PASV command. This IP should match the IP of the Spectrum app.

Some FTP servers also allow dynamic resolving of hostnames. In this case, it is recommended to use the Spectrum app URL instead of the IP.

Example configuration for [vsftpd ↗](https://security.appspot.com/vsftpd.html):

> Terminal window
> 
> ```
> 
> pasv_min_port=20000
> 
> pasv_max_port=20020
> 
> 
> pasv_enable=YES
> 
> pasv_address=ftp.example.com
> 
> pasv_addr_resolve=YES
> 
> pasv_promiscuous=YES
> 
> 
> ```

### Spectrum FTPS (ProFTPD) instructions

To use Spectrum TCP to proxy and protect FTPS, specifically ProFTPD, the following example configuration is recommended:

* **Control Port**: Port 21
* **Data Ports**: Port ranges 50000-50500

On the ProFTPD server side use the following example configuration:

* `MasqueradeAddress`: `www.example.com`
* `AllowForeignAddress`: You can use the option `on` to allow all IPs, but it is recommended to only allow [Cloudflare IP](https://developers.cloudflare.com/fundamentals/concepts/cloudflare-ip-addresses/#allow-cloudflare-ip-addresses).
* `PassivePorts`: `50000-50500`

For more details, refer to the [ProFTPD documentation ↗](http://www.proftpd.org/docs/modules/mod%5Fcore.html).

## SFTP

Unlike FTP or FTPS, enabling Spectrum for SFTP does not require extra configuration. When setting up a Spectrum application for SSH, select port 22 and TCP.

## Microsoft Windows IIS FTP

Refer to the [Microsoft Windows IIS documentation ↗](https://docs.microsoft.com/en-us/iis/publish/using-the-ftp-service/configuring-ftp-firewall-settings-in-iis-7#step-1-configure-the-passive-port-range-for-the-ftp-service) to configure a static data port range and external IP matching your Spectrum application.

Additionally, IIS requires that the source IP for both, FTP control and data connections are the same. However, when using Spectrum, this requirement may not be met, as both connections often terminate on different servers with their own unique egress IPs. To ensure proper functionality, also set `dataChannelSecurity/matchClientAddressForPasv = false`. Refer to [Microsoft Windows IIS FTP Official Guide ↗](https://learn.microsoft.com/en-us/iis/configuration/system.applicationhost/sites/site/ftpserver/security/datachannelsecurity) for further details.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/about/","name":"About"}},{"@type":"ListItem","position":4,"item":{"@id":"/spectrum/about/ftp/","name":"FTP"}}]}
```

---

---
title: Cloudflare Load Balancing
description: Add TCP health checks, failover, and traffic steering to Spectrum applications.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare Load Balancing

You can configure Spectrum with Cloudflare [Load Balancing](https://developers.cloudflare.com/load-balancing/) to provide TCP healthchecks, failover, and traffic steering, bringing resiliency to your Spectrum applications.

For an overview of how Cloudflare Load Balancing works refer to [Load Balancing components](https://developers.cloudflare.com/load-balancing/understand-basics/load-balancing-components/). For setup guidance refer to [Add load balancing to Spectrum applications](https://developers.cloudflare.com/load-balancing/additional-options/spectrum/).

## TCP health checks

You can configure a Cloudflare load balancer to probe any TCP port for an accepted connection, which is in addition to HTTP and HTTPS probing capabilities.

Health checks are optional within a load balancer. However, without a health check, the load balancer will distribute traffic to all endpoints in the first pool. With the health checks enabled, hosts that have gone into an error state will not receive traffic, maintaining uptime. This allows you to enable intelligent failover within a pool of hosts or amongst multiple pools.

The example below shows a TCP health check configuration for an application running on port 2408 with a refresh rate every 30 seconds. You can configure TCP health checks through the dashboard or through Cloudflare's API.

TCP health check - Dashboard example

| Field | Value |
| ----- | ----- |
| Type  | TCP   |
| Port  | 2408  |

Under **Advanced health check settings**:

| Field    | Value     |
| -------- | --------- |
| Interval | 30        |
| Timeout  | 5 seconds |
| Retries  | 2         |

TCP health check - API example

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Load Balancing: Monitors and Pools Write`

Create Monitor

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/load_balancers/monitors" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "description": "Spectrum Health Check",

    "type": "tcp",

    "port": 2048,

    "interval": 30,

    "retries": 2,

    "timeout": 5,

    "method": "connection_established"

  }'


```

```

{

    "result": {

        "description": "TCP Monitor for Spectrum",

        "created_on": "2025-07-17T14:55:04.830009Z",

        "modified_on": "2025-07-17T14:55:04.830009Z",

        "id": "1d404721c660a8a7aaa28d68ed6d48d9",

        "type": "tcp",

        "port": 2048,

        "interval": 60,

        "retries": 2,

        "timeout": 5,

        "expected_body": "",

        "expected_codes": "",

        "follow_redirects": false,

        "allow_insecure": false,

        "probe_zone": "",

        "path": "",

        "method": "connection_established"

    },

    "success": true,

    "errors": [],

    "messages": []

}


```

## Traffic steering

All traffic steering policies are available for transport load balancing through Spectrum. Refer to the Load Balancing documentation to learn more about the available [global traffic steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/steering-policies/) and [endpoint steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/) options.

## Weights

[Endpoint weights](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/origin-level-steering/#weights) allow you to have endpoints with different capacity or to split traffic amongst hosts for any other reason.

Weight configured within a load balancer pool will be honored with load balancing through Spectrum.

## Requirements and limitations

* Load Balancing [session affinity](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/), [failover across pools](https://developers.cloudflare.com/load-balancing/understand-basics/adaptive-routing/#failover-across-pools), and [custom rules](https://developers.cloudflare.com/load-balancing/additional-options/load-balancing-rules/) are not supported by Spectrum.
* UDP health checks are only available with public monitoring. TCP can be used with both public and private monitoring.
* This feature requires an Enterprise plan. If you would like to upgrade, contact your account team.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/about/","name":"About"}},{"@type":"ListItem","position":4,"item":{"@id":"/spectrum/about/load-balancer/","name":"Cloudflare Load Balancing"}}]}
```

---

---
title: Static IP
description: Assign persistent IP addresses to your Spectrum applications.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Static IP

When you create a Spectrum application, you are assigned an IP. These IPs are normally dynamic, meaning that they will change over time. But, for instance, if you want to set up WAF custom rules for specific IPs, you may want to use static IPs.

A static IP, like a physical street address can tell other computers or servers on the Internet where a specific computer is located or connected. This makes the device easier to find on the network, since the IP will not change.

With static IPs, Cloudflare commits to never changing the IP address of a client's domain resolved at the Cloudflare global network. For example, `www.example.com` will always resolve and accept traffic sent to `198.51.100.10`. No other customer will be hosted on that IP.

Importantly, the static IP is associated with the DNS name, not with each individual Spectrum application. This means that all Spectrum apps using the same hostname will share the same static IP.

## Use static IPs with Spectrum

Availability

Static IP is an Enterprise feature that does not come standard with Spectrum. Contact your account team to request access.

Once you get your static IP from Cloudflare, you can use it via API, just like [BYOIP](https://developers.cloudflare.com/byoip/). For the moment, there is still no UI available for this feature.

When creating a Spectrum application through the API, specify the static IPs that you have been provided. See, for instance, the API example below that creates an application routing traffic through Cloudflare’s HTTP pipeline.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`

Create Spectrum application using a name for the origin

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/spectrum/apps" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "protocol": "tcp/80",

    "dns": {

        "type": "ADDRESS",

        "name": "www.example.com"

    },

    "origin_direct": [

        "tcp://192.0.2.1:80"

    ],

    "tls": "off",

    "traffic_type": "http",

    "edge_ips": {

        "type": "static",

        "ips": [

            "198.51.100.10",

            "2001:DB8::1"

        ]

    }

  }'


```

## Check your static IPs

You can find your leased static IPs for Spectrum on the dashboard under [**Address space** \> **Leased IPs** ↗](https://dash.cloudflare.com/?to=/:account/ip-addresses/address-space).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/about/","name":"About"}},{"@type":"ListItem","position":4,"item":{"@id":"/spectrum/about/static-ip/","name":"Static IP"}}]}
```

---

---
title: Enable Proxy protocol
description: Pass client IP information to your origin using Proxy protocol v1 or Simple Proxy Protocol.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Enable Proxy protocol

Because Cloudflare intercepts packets before forwarding them to your server, if you were to look up the client IP, you would see Cloudflare's IP rather than the true client IP.

Some services you run may require knowledge of the true client IP. In those cases, you can use a proxy protocol for Cloudflare to pass on the client IP to your service. Sending proxy information along is dependent on whether TCP or UDP is used. For TCP, Spectrum supports adding [Proxy Protocol v1 ↗](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt), which is the human readable version supported by Amazon ELB and [NGINX ↗](https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/). For UDP applications, Cloudflare has developed a custom proxy protocol called Simple Proxy Protocol. Be aware that Proxy Protocol is not supported for Spectrum egresses to Cloudflare WAN (formerly Magic WAN).

Note

This feature requires an Enterprise plan. If you would like to upgrade, contact your account team.

## Enable Proxy Protocol v1 for TCP

1. In the Cloudflare dashboard, go to the **Spectrum** page.  
[ Go to **Spectrum** ](https://dash.cloudflare.com/?to=/:account/:zone/spectrum)
2. Locate the application that will use the PROXY protocol and select **Configure**.
3. From the dropdown, select **PROXY Protocol v1**.

When TCP applications are configured to use **PROXY Protocol v1**, Cloudflare will prepend each inbound TCP connection with the PROXY Protocol plain-text header.

### The Proxy Protocol v1 Header

PROXY Protocol prepends every connection with a header reporting the client IP address and port. A PROXY Protocol plain-text header has the format:

```

PROXY_STRING + single space + INET_PROTOCOL + single space + CLIENT_IP + single space + PROXY_IP + single space + CLIENT_PORT + single space + PROXY_PORT + "\r\n"


```

An example PROXY Protocol line for an IPv4 address would look like:

```

PROXY TCP4 192.0.2.0 192.0.2.255 42300 443\r\n


```

An example PROXY Protocol line for an IPv6 address would look like:

```

PROXY TCP6 2001:db8:: 2001:db8:ffff:ffff:ffff:ffff:ffff:ffff 42300 443\r\n


```

## Enable Proxy Protocol v2 for TCP/UDP

1. In the Cloudflare dashboard, go to the **Spectrum** page.  
[ Go to **Spectrum** ](https://dash.cloudflare.com/?to=/:account/:zone/spectrum)
2. Locate the application that will use the PROXY protocol and select **Configure**.
3. From the dropdown, select **PROXY Protocol v2**.

When TCP applications are configured to use **PROXY Protocol v2**, Cloudflare will prepend each inbound TCP connection with the PROXY Protocol binary header.

When UDP applications are configured to use **PROXY Protocol v2**, Cloudflare will prepend the first UDP datagram on a stream with a PROXY Protocol binary header.

### The Proxy Protocol v2 Header

PROXY Protocol prepends every connection with a header reporting the client IP address and port.

A PROXY Protocol binary header for a IPv4 incoming address has the format:

```

 0                   1                   2                   3

 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|                                                               |

+                                                               +

|                  Proxy Protocol v2 Signature                  |

+                                                               +

|                                                               |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|Version|Command|   AF  | Proto.|         Address Length        |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|                      IPv4 Source Address                      |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|                    IPv4 Destination Address                   |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|          Source Port          |        Destination Port       |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


```

A PROXY Protocol binary header for a IPv6 incoming address has the format:

```

 0                   1                   2                   3

 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|                                                               |

+                                                               +

|                  Proxy Protocol v2 Signature                  |

+                                                               +

|                                                               |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|Version|Command|   AF  | Proto.|         Address Length        |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|                                                               |

+                                                               +

|                                                               |

+                      IPv6 Source Address                      +

|                                                               |

+                                                               +

|                                                               |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|                                                               |

+                                                               +

|                                                               |

+                    IPv6 Destination Address                   +

|                                                               |

+                                                               +

|                                                               |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|          Source Port          |        Destination Port       |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


```

## Enable Simple Proxy Protocol for UDP

When using Spectrum for UDP, the client source IP and port information can be obtained by using Simple Proxy Protocol, a lightweight protocol developed specifically for UDP.

To enable it, select **Configure** on a Spectrum application and toggle the setting for Simple Proxy Protocol to **On**.

Simple Proxy Protocol dictates that your origin must also prepend packets meant for the client with the same header, including original client source information. This is done to validate that packets coming in are in fact intended for the client.

For more information about Simple Proxy Protocol headers, refer to [Simple Proxy Protocol headers](https://developers.cloudflare.com/spectrum/reference/simple-proxy-protocol-header/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/spectrum/how-to/enable-proxy-protocol/","name":"Enable Proxy protocol"}}]}
```

---

---
title: Analytics
description: Metrics tracked for every Spectrum connection, including bytes and connection duration.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Analytics

Cloudflare measures the following metrics for every connection.

| Metric         | Name                                | Example | Unit                 |
| -------------- | ----------------------------------- | ------- | -------------------- |
| count          | Count of total events               | 1000    | Count                |
| bytesIngress   | Sum of ingress bytes                | 1000    | Sum                  |
| bytesEgress    | Sum of egress bytes                 | 1000    | Sum                  |
| durationAvg    | Average connection duration         | 1.0     | Time in milliseconds |
| durationMedian | Median connection duration          | 1.0     | Time in milliseconds |
| duration90th   | 90th percentile connection duration | 1.0     | Time in milliseconds |
| duration99th   | 99th percentile connection duration | 1.0     | Time in milliseconds |

## Additional dimensions

You can divide your analytics further by the following dimensions.

| Dimension | Name                          | Example                                                    |
| --------- | ----------------------------- | ---------------------------------------------------------- |
| event     | Connection Event              | connect, progress, disconnect, originError, clientFiltered |
| appID     | Application ID                | 40d67c87c6cd4b889a4fd57805225e85                           |
| coloName  | Colo Name                     | SFO                                                        |
| ipVersion | IP version used by the client | 4, 6                                                       |

## Operators for filtering

Use the operators below to filter data.

| Operator | Name                     | URL Encoded |
| -------- | ------------------------ | ----------- |
| \==      | Equals                   | %3D%3D      |
| !=       | Does not equal           | !%3D        |
| \>       | Greater Than             | %3E         |
| <        | Less Than                | %3C         |
| \>=      | Greater than or equal to | %3E%3D      |
| <=       | Less than or equal to    | %3C%3D      |

Combine filters using `OR` and `AND` boolean logic:

* `AND` takes precedence over `OR` in all expressions.
* The `OR` operator is defined using a comma `,` or the `OR` keyword surrounded by whitespace.
* The `AND` operator is defined using a semicolon `;` or the `AND` keyword surrounded by whitespace.  
Note  
Note that the semicolon is a reserved character in URLs ([RFC 1738 ↗](https://www.rfc-editor.org/rfc/rfc1738)) and should be percent-encoded as `%3B`.

## Analytics request structure

```

/api/v4/zones/{zone_id}/spectrum/analytics/events/summary?metrics=METRICS&dimensions=DIMENSIONS&filters=FILTERS&since=FROM_TS&sort=SORT&until=TO_TS&limit=LIMIT

/api/v4/zones/{zone_id}/spectrum/analytics/events/bytime?metrics=METRICS&dimensions=DIMENSIONS&filters=FILTERS&since=FROM_TS&sort=SORT&until=TO_TS&limit=LIMIT


```

* METRICS is one or more metrics (such as count) to compute
* DIMENSIONS can be used to break down the data by given attributes
* FILTERS used to filter rows by one or more dimensions (see Filters section below)
* SORT is the sort order for the result set; sort fields must be included in METRICS or DIMENSIONS
* TO\_TS is that end of time interval to query, defaults to current time
* FROM\_TS is that start of time interval to query, defaults to TO\_TS - 6 hours
* STEP is used to select time series resolution when using endpoint:
* auto or omitted - selects time step most appropriate to time interval  
   * year  
   * quarter  
   * month  
   * week  
   * day  
   * hour

## Analytics query example

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Analytics Read`

Get analytics summary

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/spectrum/analytics/events/summary" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

Refer to the [Spectrum API documentation](https://developers.cloudflare.com/api/resources/spectrum/subresources/analytics/subresources/aggregates/subresources/currents/methods/get/) for more examples of API requests.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/spectrum/reference/analytics/","name":"Analytics"}}]}
```

---

---
title: Configuration options
description: Configurable options for Spectrum applications, including edge and origin ports and protocols.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configuration options

Spectrum is a global TCP and UDP proxy running on Cloudflare's edge nodes. It does not terminate the connection in the application-layer sense. However, at Layer 4, Spectrum does terminate the TCP and UDP sockets in both directions. The L4 payloads of TCP segments and UDP datagrams are passed back and forth as-is, without modifications.

Note

Some of these features require an Enterprise plan. If you would like to upgrade, contact your account team.

## Application type

The application type determines the protocol by which data travels from the edge to your origin. Select _TCP/UDP_ if you want to proxy directly to the origin. If you want to set up products like CDN, Workers, or Bot management, you need to select _HTTP/HTTPS_. In this case, traffic is routed through Cloudflare's pipeline instead of connecting directly to your origin.

## IP addresses

When a Spectrum application is created, it is assigned a unique IPv4 and IPv6 address, or you can provision the application to be IPv6 only. The addresses are not static, and they may change over time. The best way to look up the current addresses is by using DNS. The DNS name of the Spectrum application will always return the IPs currently dedicated to the application.

The addresses are anycasted from all Cloudflare data centers, with the exception of data centers in China.

## SMTP

Spectrum can act as a TCP load balancer in front of an SMTP server but will not act as an intermediary mail server. Instead, Spectrum passes data through to your origin. The client IP shown on mail will be the Cloudflare edge IP. If the mail server requires knowing the true client IP, it should use Proxy Protocol to get the source IP from Cloudflare. Cloudflare recommends enabling Proxy Protocol on applications configured to proxy SMTP.

SMTP servers may perform a series of checks on servers attempting to send messages through it. These checks are intended to filter requests from illegitimate servers.

Messages may be rejected if:

* A reverse DNS lookup on the IP address of the connecting server returns a negative response.
* The reverse DNS lookup produces a different hostname than what was sent in the SMTP `HELO`/`EHLO` message.
* The reverse DNS lookup produces a different hostname than what is advertised in your SMTP server's banner.
* The result of a reverse DNS lookup does not match a corresponding forward DNS lookup.

Spectrum applications do not have reverse DNS entries.

Additionally, SMTP servers may perform a DNS lookup to find the MX records for a domain. Messages from your server may be rejected if an MX record for your domain is associated with a Spectrum application, as the IP address of server will not match the Spectrum IP address.

## Ports

Cloudflare supports all TCP ports.

## Port ranges

Spectrum applications can be configured to proxy traffic on ranges of ports.

For direct origins:

```

{

  "protocol": "tcp/1000-2000",

  "dns": {

    "type": "CNAME",

    "name": "range.example.com"

  },

  "origin_direct": ["tcp://192.0.2.1:3000-4000"]

}


```

For DNS origins:

```

{

  "protocol": "tcp/1000-2000",

  "dns": {

    "type": "CNAME",

    "name": "range.example.com"

  },

  "origin_dns": {

    "name": "origin.example.com",

    "ttl": 1200

  },

  "origin_port": "3000-4000"

}


```

The number of ports in an origin port range must match the number of ports specified in the `protocol` field. Connections to a port within a port range at the edge will be proxied to the equivalent port offset in the origin range. For example, in the configurations above, a connection to `range.example.com:1005` would be proxied to port `3005` on the origin.

## IP Access rules

If [IP Access rules](https://developers.cloudflare.com/waf/tools/ip-access-rules/create/) are enabled for a Spectrum application, Cloudflare will respect the IP Access rules configured for that domain. Cloudflare only respects rules created for specific IP addresses, IP blocks, countries, or ASNs for Spectrum applications. Spectrum will also only respect rules created with the actions `allow` or `block`.

Note

Network analytics data for Spectrum does not reflect the outcomes of IP Access rules. Instead, to verify whether traffic was allowed or blocked based on these rules, consult the Spectrum event logs.

## Argo Smart Routing

Once Argo Smart Routing is enabled for your application, traffic will automatically be routed through the fastest and most reliable network path available. Argo Smart Routing is available for TCP and UDP (beta) applications.

## Edge TLS Termination

If you enable **Edge TLS Termination** for a Spectrum application, Cloudflare will encrypt traffic for the application at the Edge. The Edge TLS Termination toggle applies only to TCP applications.

Spectrum offers three modes of TLS termination: 'Flexible', 'Full', and 'Full (Strict)'.

'Flexible' enables termination of the client connection at the edge, but does not enable TLS from Cloudflare to your origin. Traffic will be sent over an encrypted connection from the client to Cloudflare, but not from Cloudflare to the origin.

'Full' specifies that traffic from Cloudflare to the origin will also be encrypted but without certificate validation. When set to 'Full (Strict)', traffic from Cloudflare to the origin will also be encrypted with strict validation of the origin certificate.

TLS versions supported by Spectrum include TLS 1.1, TLS 1.2, and TLS 1.3.

You can manage this through the Spectrum app at the Cloudflare dashboard, or using the [Spectrum API endpoint](https://developers.cloudflare.com/api/resources/spectrum/subresources/apps/methods/update/).

Note

If you have the TLS termination setting configured to **off**, this means that Spectrum will then proxy connections to the origin without decrypting. The certificate that is presented in this case will be the certificate installed at your origin server, instead of the Edge Certificate from Cloudflare.

Warning

If you need to control TLS settings, like the minimum TLS version or cipher suites, you need to use an HTTPS application. For TCP applications, default settings will apply. The minimum TLS version will be 1.1 and the cipher suites are:

| OpenSSL Name                  |
| ----------------------------- |
| AEAD-CHACHA20-POLY1305-SHA256 |
| AEAD-AES128-GCM-SHA256        |
| AEAD-AES256-GCM-SHA384        |
| ECDHE-RSA-CHACHA20-POLY1305   |
| ECDHE-ECDSA-CHACHA20-POLY1305 |
| ECDHE-RSA-AES128-GCM-SHA256   |
| ECDHE-ECDSA-AES128-GCM-SHA256 |
| ECDHE-RSA-AES256-GCM-SHA384   |
| ECDHE-ECDSA-AES256-GCM-SHA384 |
| ECDHE-RSA-AES128-SHA256       |
| ECDHE-RSA-AES128-SHA          |
| CDHE-ECDSA-AES128-SHA256      |
| ECDHE-ECDSA-AES128-SHA        |
| ECDHE-RSA-AES256-SHA          |
| ECDHE-ECDSA-AES256-SHA        |
| AES128-GCM-SHA256             |
| AES256-GCM-SHA384             |
| AES128-SHA256                 |
| AES128-SHA                    |
| AES256-SHA                    |
| ECDHE-RSA-DES-CBC3-SHA        |
| DES-CBC3-SHA                  |

## Origin TLS Termination

Below are the cipher suites Cloudflare presents to origins during an SSL/TLS handshake. For cipher suites supported at our edge or presented to browsers and other user agents, refer to [Cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/).

The cipher suites below are ordered based on how they appear in the ClientHello, communicating our preference to the origin. Customers do not have the ability to modify the ciphers used by Spectrum.

## Supported cipher suites by protocol

| OpenSSL Name                                         | TLS 1.1 | TLS 1.2 | TLS 1.3 |
| ---------------------------------------------------- | ------- | ------- | ------- |
| AEAD-AES128-GCM-SHA256[1](#user-content-fn-1)        | ❌       | ❌       | ✅       |
| AEAD-AES256-GCM-SHA384[1](#user-content-fn-1)        | ❌       | ❌       | ✅       |
| AEAD-CHACHA20-POLY1305-SHA256[1](#user-content-fn-1) | ❌       | ❌       | ✅       |
| ECDHE-ECDSA-AES128-GCM-SHA256                        | ❌       | ✅       | ❌       |
| ECDHE-RSA-AES128-GCM-SHA256                          | ❌       | ✅       | ❌       |
| ECDHE-RSA-AES128-SHA                                 | ✅       | ✅       | ❌       |
| AES128-GCM-SHA256                                    | ❌       | ✅       | ❌       |
| AES128-SHA                                           | ✅       | ✅       | ❌       |
| AES256-SHA                                           | ✅       | ✅       | ❌       |

## Footnotes

1. Although TLS 1.3 uses the same cipher suite space as previous versions of TLS, TLS 1.3 cipher suites are defined differently, only specifying the symmetric ciphers, and cannot be used for TLS 1.2\. Similarly, TLS 1.2 and lower cipher suites cannot be used with TLS 1.3 ([RFC 8446 ↗](https://www.rfc-editor.org/rfc/rfc8446.html)). BoringSSL also hard-codes cipher preferences in this order for TLS 1.3\. Refer to [TLS 1.3 cipher suites](https://developers.cloudflare.com/ssl/origin-configuration/cipher-suites/#tls-13-cipher-suites) for details. [↩](#user-content-fnref-1) [↩2](#user-content-fnref-1-2) [↩3](#user-content-fnref-1-3)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/spectrum/reference/configuration-options/","name":"Configuration options"}}]}
```

---

---
title: Why Spectrum-enabled hostnames might appear in Layer 7 Analytics
description: How Spectrum Layer 4 traffic can appear in Layer 7 analytics dashboards.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Why Spectrum-enabled hostnames might appear in Layer 7 Analytics

Even when you have Spectrum enabled to handle Layer 4 traffic (for example, TCP/UDP connections), you may still notice traffic in your Layer 7 (L7) analytics dashboard. This is due to the way Cloudflare's Layer 7 CDNand Spectrum handle customer identity differently.

## How Spectrum identifies a user (Layer 4)

In Spectrum, the identity of the customer hostname is based on the Cloudflare IP address that the client uses to connect to the edge. Here is the typical process:

1. Spectrum sets up a DNS hostname in the customer's zone that points to its Spectrum edge IP, and links this edge IP and port to the customer's configuration.
2. The client performs a DNS lookup on the Spectrum hostname, retrieves the Spectrum edge IP, and connects to that IP and port.
3. Spectrum uses this edge IP and port to match the connection to the customer's configuration, identifying the customer.

This process focuses on Layer 4 associating a hostname and customer configuration around IP addresses and ports.

## How the CDN identifies a user (Layer 7)

1. The customer sets up a DNS hostname in their zone that directs traffic to their origin server.
2. The client performs a DNS lookup on the CDN hostname, and the DNS server responds with a CDN edge IP. In contrast to Spectrum, the CDN edge IP is primarily used for traffic management rather than customer identity, as multiple customers can share the same CDN edge IP.

For the CDN, identifying the customer relies heavily on resolving hostnames during the TLS handshake (SNI) and the HTTP request (`Host` header). Notably, the CDN is designed to accept any hostname that matches the customer's zone (for example, `*.example.com`), even if there is no specific Layer 7 DNS match. This means that even Spectrum or Load Balancer hostnames will be accepted as valid under `*.example.com`.

## The overlap: Layer 7 traffic being proxied through Spectrum

Because the CDN is designed to accept any hostname under your zone (for example, `spectrum.example.com`), HTTP traffic that should first be proxied by Spectrum, or even HTTP traffic meant for a Layer-4-only Spectrum app, may sometimes be processed directly by the Layer 7 CDN system. The process is the following:

1. The client connects to a Layer 7 CDN edge IP while using the hostname of a Spectrum application (for example, `spectrum.example.com`) during both the TLS handshake and the HTTP request. Essentially, this means the client is attempting to access `spectrum.example.com` on an incorrect IP.
2. The CDN accepts this hostname as part of the customer zone during both the TLS and HTTP phases because it is designed to recognize any hostname under `*.example.com`. As a result, the request passes through the CDN under the zone's identity.
3. However, when the CDN attempts to connect to the origin server, it performs an internal DNS lookup of the HTTP hostname, which resolves to the Spectrum IP (from `spectrum.example.com` to the Spectrum edge IP). Consequently, the CDN establishes an origin connection to Spectrum, loading its configuration and forwarding the request to the Spectrum origin.

This means traffic for this hostname undergoes the standard Layer 7 CDN products, including Analytics and logs.

## Blocking unwanted L7 traffic

If you want to prevent traffic for Layer-4-only Spectrum hostnames from being proxied through Layer 7 to your origin (including unwanted scans or requests), we recommend implementing a Layer 7 WAF (Web Application Firewall) rule. This rule can block traffic directed at specific hostnames or ports, ensuring that only legitimate traffic reaches your Spectrum service.

For example, you can create a WAF rule to block requests to `spectrum.example.com` unless they originate from a Spectrum IP or a customer's Spectrum BYOIP. The traffic will still be logged in Layer 7 Analytics, including WAF Security Events, but this prevents it from arriving at the wrong address and looping through the CDN a second time.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/spectrum/reference/layer-7-analytics/","name":"Why Spectrum-enabled hostnames might appear in Layer 7 Analytics"}}]}
```

---

---
title: Limitations
description: Protocol-specific limitations for Spectrum applications.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Limitations

The following limitations apply to different protocols supported by Spectrum.

## HTTPS

At the moment, HTTPS applications do not support HTTP/3.

## UDP

At the moment, Cloudflare does not support packet fragmentation for UDP packets. If packets are fragmented, they will be dropped at Cloudflare’s edge. Additionally, UDP Spectrum applications are not supported on Magic Transit, BYOIP, Spectrum, and Bindings.

## Minecraft

Minecraft Java Edition is supported but Minecraft Bedrock Edition is not supported.

## Universal SSL

[Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) is not compatible with Cloudflare Spectrum. Use either an [advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) or a [custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) instead.

## Private Network Load Balancing

When using [Spectrum](https://developers.cloudflare.com/load-balancing/private-network/#on-ramps) as an on-ramp and [Cloudflare WAN](https://developers.cloudflare.com/load-balancing/private-network/#cloudflare-wan) as an off-ramp the [proxy protocol](https://developers.cloudflare.com/spectrum/how-to/enable-proxy-protocol/) setting in Spectrum is not supported.

## Cloudflare Tunnel

Integrating Spectrum with [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/) is only supported for **HTTP/HTTPS** applications. This is because Spectrum must upstream the request through the [Layer 7 CDN products](https://developers.cloudflare.com/spectrum/reference/layer-7-analytics/#the-overlap-layer-7-traffic-being-proxied-through-spectrum) to reach the Tunnel service.

To correctly route traffic from Spectrum through a Cloudflare Tunnel, you must:

1. Configure your Spectrum application with the type set to **HTTP** or **HTTPS**.
2. Point the Spectrum application's origin to a hostname that is already [routing traffic](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/routing-to-tunnel/) through your Cloudflare Tunnel (for example, via a [DNS record](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/routing-to-tunnel/dns/) or [Cloudflare Load Balancer](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/routing-to-tunnel/public-load-balancers/)).

Using a Spectrum application of any other type (for example, TCP) with a Cloudflare Tunnel origin is not supported. Pointing a Spectrum application's origin directly to your Tunnel's subdomain (`<UUID>.cfargotunnel.com`) is also not a valid configuration and will not work.

## Listen on ports configuration

By default, Spectrum is configured to listen on all ports, which can raise concerns for security auditors. However, it is important to note that Spectrum will only proxy connections from edge ports that are specifically configured within Cloudflare.

When a TCP handshake is initiated to any port for a Spectrum IP, the handshake will always be completed. If there is a Spectrum application configured for the port, the connection will be proxied to origin. If no application is configured, the connection is immediately terminated and no origin connection will be opened.

Spectrum will only ever proxy traffic to an origin if there is a Spectrum application configured for that port.

## IP access control

Currently, [custom rules](https://developers.cloudflare.com/waf/custom-rules/) do not work with Spectrum applications. Use [IP Access rules](https://developers.cloudflare.com/waf/tools/ip-access-rules/) to allowlist, block, and challenge traffic for Spectrum applications based on the request's IP address, Autonomous System Number (ASN), or country.

Refer to [Configuration options](https://developers.cloudflare.com/spectrum/reference/configuration-options/#ip-access-rules) for more information.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/spectrum/reference/limitations/","name":"Limitations"}}]}
```

---

---
title: Event logs
description: Access Spectrum connection lifecycle logs through Logpush.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Event logs

Spectrum logs the entire lifecycle of every client that connects through it. These event logs are available through Logpush as a separate category (dataset type `spectrum_events`); they are not part of HTTP log events.

For each connection, Spectrum logs a connect event and either a disconnect or error event. Details on status codes can be found below.

## Configure Logpush

Spectrum [log events](https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/) can be configured through the dashboard or API, depending on your preferred [destination](https://developers.cloudflare.com/logs/logpush/logpush-job/enable-destinations/).

## Status Codes

| Code | Description                                                                                        |
| ---- | -------------------------------------------------------------------------------------------------- |
| 0    | Connection was opened successfully.                                                                |
| 200  | Normal connection closure.                                                                         |
| 400  | The TLS client hello sent during the client/edge TLS handshake contained an invalid SNI.           |
| 403  | Connection closed because the client IP matched a firewall rule with deny action.                  |
| 443  | The client TLS handshake failed.                                                                   |
| 444  | The origin closed the connection by sending a reset (RST) packet. Not all data may have been sent. |
| 445  | A timeout event (ETIMEDOUT) occurred on an established connection to origin.                       |
| 446  | Origin keepalive expired (EHOSTUNREACH).                                                           |
| 447  | Error while reading from or writing to an established origin connection (ECONNREFUSED).            |
| 448  | Origin connection closed due to a broken pipe (EPIPE).                                             |
| 490  | Client TLS error on established connection.                                                        |
| 495  | Client connection received an error (ECONNREFUSED).                                                |
| 496  | Client host is unreachable (EHOSTUNREACH).                                                         |
| 497  | A timeout event (ETIMEDOUT) occurred on an established connection to client.                       |
| 498  | Established client connection closed due to broken pipe (EPIPE).                                   |
| 499  | The client closed the connection by sending a reset (RST) packet. Not all data may have been sent. |
| 500  | Internal Cloudflare error.                                                                         |
| 503  | Error related to performing the TLS handshake with keyless SSL.                                    |
| 520  | Unknown origin connection error.                                                                   |
| 521  | Origin refused to open the connection (ECONNREFUSED).                                              |
| 522  | Opening a connection to origin failed: ETIMEDOUT                                                   |
| 523  | Opening a connection to origin failed: ENETUNREACH                                                 |
| 524  | Opening a connection to origin failed due to an internal system error.                             |
| 530  | Internal error while resolving origin to an IP.                                                    |
| 531  | Could not resolve origin to an IP.                                                                 |
| 532  | The origin connection was not opened because the origin IP is blocked.                             |
| 533  | Internal error while resolving origin to an IP.                                                    |
| 540  | The client/edge TLS handshake failed due to an invalid configuration.                              |
| 999  | Unknown connection error.                                                                          |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/spectrum/reference/logs/","name":"Event logs"}}]}
```

---

---
title: Settings by plan
description: Spectrum API fields and settings available by Cloudflare plan.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Settings by plan

Certain fields in Spectrum request and response bodies require an Enterprise plan. To upgrade your plan, contact your account team.

Spectrum properties requiring an Enterprise plan:

| Name                 | Type    | Description                                                                                                                                                                                                                                                                                          | Example                                                   |
| -------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| origin\_dns          | object  | Method and parameters used to discover the origin server address via DNS. Valid record types are A, AAAA, SRV and empty (both A and AAA).A request must contain either an origin\_dns parameter or an origin\_direct parameter. When both are specified the service returns an HTTP 400 Bad Request. | origin\_dns: {type: A, name: mqtt.example.com, ttl: 1200} |
| origin\_port         | integer | The destination port at the origin.                                                                                                                                                                                                                                                                  | 22                                                        |
| proxy\_protocol      | string  | Enables Proxy Protocol to the origin. Spectrum supports v1, v2, and simple proxy protocols. Refer to [Proxy Protocol](https://developers.cloudflare.com/spectrum/how-to/enable-proxy-protocol/) for more details.                                                                                    | off                                                       |
| ip\_firewall         | boolean | Enables IP Access rules for this application.                                                                                                                                                                                                                                                        | true                                                      |
| tls                  | string  | Type of TLS termination for the application. Options are off (default, also known as Passthrough), flexible, full, and strict. Refer to [Configuration Options](https://developers.cloudflare.com/spectrum/reference/configuration-options/) for descriptions of each.                               | full                                                      |
| argo\_smart\_routing | boolean | Enables Argo Smart Routing for the application. Note that it is only available for TCP applications with traffic\_type set to direct.                                                                                                                                                                | true                                                      |

Review the [Spectrum API documentation](https://developers.cloudflare.com/api/resources/spectrum/subresources/apps/methods/list/) for example API requests.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/spectrum/reference/settings-by-plan/","name":"Settings by plan"}}]}
```

---

---
title: Simple Proxy Protocol Header
description: Format of the Simple Proxy Protocol header prepended to UDP datagrams.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Simple Proxy Protocol Header

The client source IP and port is encoded in a fixed-length, 38-octet long header and prepended to the payload of each proxied UDP datagram in the format described below.

```

 0                   1                   2                   3

 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|          Magic Number         |                               |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +

|                                                               |

+                                                               +

|                                                               |

+                         Client Address                        +

|                                                               |

+                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|                               |                               |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +

|                                                               |

+                                                               +

|                                                               |

+                         Proxy Address                         +

|                                                               |

+                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|                               |         Client Port           |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|           Proxy Port          |          Payload...           |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


```

The contents of the header are below.

## Magic Number

16-bit fixed value set to 0x56EC for SPP. This field should be used to identify the SPP protocol and its SPP 38-byte header.

## Client Address

128-bit address of the originator of the proxied UDP datagram, that is, the client. An IPv6 address if the client used IPv6 addressing, or an IPv4-mapped IPv6 address (refer to [RFC 4291 ↗](https://tools.ietf.org/html/rfc4291)) in case of an IPv4 client.

## Proxy address

128-bit address of the recipient of the proxied UDP datagram, that is the proxy. Contents should be interpreted in the same way as the Client Address.

## Client port

16-bit source port number of the proxied UDP datagram. In other words, the UDP port number from which the client sent the datagram.

## Proxy port

16-bit destination port number of the proxied UDP datagram. In other words, the UDP port number on which the proxy received the datagram.

## Payload

Data following the header carried by the datagram. Magic number, addresses, and port numbers are encoded in network byte order.

A corresponding C structure describing the header is:

```

struct {

    uint16_t magic;

    uint8_t  client_addr[16];

    uint8_t  proxy_addr[16];

    uint16_t client_port;

    uint16_t proxy_port;

};


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/spectrum/","name":"Spectrum"}},{"@type":"ListItem","position":3,"item":{"@id":"/spectrum/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/spectrum/reference/simple-proxy-protocol-header/","name":"Simple Proxy Protocol Header"}}]}
```

---

---
title: Speed
description: Optimize your website performance with Cloudflare Speed tools and settings.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Speed

Improve the performance of your website or web application.

 Available on all plans 

Speed allows you to assess the performance of your website and get recommendations of Cloudflare products to enhance the website performance.

---

## Features

###  Observatory 

Use Observatory to conduct tests with both synthetic and real user data to identify potential website performance enhancements.

[ Use Observatory ](https://developers.cloudflare.com/speed/observatory/) 

###  Settings 

Get recommendations of Cloudflare products and settings to improve your website’s performance.

[ Use Settings ](https://developers.cloudflare.com/speed/optimization/) 

###  Aggregated Internet Measurement 

Understand your Internet quality to identify scenarios that your Internet connection is good or bad for.

[ Use Aggregated Internet Measurement ](https://developers.cloudflare.com/speed/aim/) 

---

## Related products

**[Cache rules](https://developers.cloudflare.com/cache/how-to/cache-rules/)** 

Customize the cache properties of your HTTP requests.

**[Cloudflare Web Analytics](https://developers.cloudflare.com/web-analytics/)** 

Understand the performance of your webpages as experienced by your site visitors.

**[Cloudflare Image Resizing](https://developers.cloudflare.com/images/optimization/transformations/overview/)** 

Transform images on Cloudflare's edge platform: resize, adjust quality, and convert images to WebP or AVIF format on demand.

**[Early Hints](https://developers.cloudflare.com/cache/advanced-configuration/early-hints/)** 

Take advantage of "server think time" to asynchronously send instructions to the browser to begin loading resources while the origin server is compiling the full response.

---

## More resources

[Quotas](https://developers.cloudflare.com/speed/observatory/run-speed-test/#quotas) 

Learn about the quota limits for the number of tests you can run per month.

[Community Forum](https://community.cloudflare.com/c/website-application-performance/88) 

Engage with other users and explore more resources on Cloudflare support forum.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}}]}
```

---

---
title: Observatory (beta)
description: Test and monitor your website performance with Cloudflare Observatory.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Observatory (beta)

Observatory uses synthetic tests and real user data from browsers to assess the performance of your website. These data sources produce metrics that provide different types of insights into your website’s performance. Cloudflare then uses the analysis run by Observatory to recommend optimizations with the tools that best suit your performance issues.

## Synthetic tests

As its name suggests, synthetic testing uses servers to simulate the conditions that a user might encounter when accessing your website. This has the advantage of being consistent, as the conditions are easily replicated each time the test is run. It also allows you to have an analysis of how a code change might affect the overall performance of your website, as well as test any URL you want. However, due to its synthetic nature, it cannot replicate the breadth and diversity of different conditions that real users will experience.

Observatory provides two different types of synthetic tests:

### Browser test

The browser test loads the requested page in a headless browser and runs Google Lighthouse on it. This reports key performance metrics and provides light suggestions for improvement.

### Network test

The network test is focused on giving a detailed breakdown of the network and back-end performance of an endpoint. For more information on metrics collected, refer to [Network monitoring metrics](https://developers.cloudflare.com/speed/observatory/test-results/#network-monitoring-metrics).

### Network comparison test

You can also compare network tests in Observatory by selecting any two completed tests. The results for each test are displayed side by side as histograms, allowing you to easily visualize and compare the full distribution of data points across both tests.

## Real user monitoring (RUM)

Real user monitoring (also known as RUM), on the other hand, captures real metrics from real users accessing a website. This provides information that synthetic tests cannot capture, as users might access your website from different parts of the world, with different network conditions, ISPs, browsers and computer hardware. However, RUM data is only applied to your own website. Real user data also includes two user interaction metrics that synthetic tests do not offer - [First Input Delay (FID) ↗](https://web.dev/fid/) and [Interaction to Next Paint (INP) ↗](https://web.dev/inp/).

Free customers have RUM enabled automatically, with EU traffic excluded, and can switch it off if they prefer. Customers on other plans may enable RUM as needed.

[ Run test ](https://developers.cloudflare.com/speed/observatory/run-speed-test/) 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/observatory/","name":"Observatory (beta)"}}]}
```

---

---
title: Observatory dashboard
description: View speed test history and performance trends in the Observatory dashboard.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Observatory dashboard

The Observatory overview dashboard provides a single view of your zone's performance over the past seven days. It combines synthetic monitoring, real user data, and Cloudflare's analysis to help you quickly identify performance bottlenecks and receive actionable recommendations.

## Suggestions

The **Suggestions** panel highlights tailored optimizations you can make to improve performance. Examples include:

* Reduce Largest Contentful Paint (LCP) with Polish.
* Reduce Time to First Byte (TTFB) with Argo Smart Routing.

These recommendations will vary based on your site's observed performance.

Selecting a suggestion expands it to show more detail:

* **Why you're seeing this**: Explains the performance issue detected.
* **What you can do**: Lists recommended actions you can take.

## Core Web Vitals

The dashboard integrates **Core Web Vitals**, showing values at the 75th percentile (p75). These metrics reflect real user experiences:

* **Largest Contentful Paint (LCP)**: How quickly the main content of a page becomes visible.
* **Interaction to Next Paint (INP)**: How responsive the site is to user interactions.
* **Cumulative Layout Shift (CLS)**: How visually stable the page layout is.

If insufficient real user data is available, metrics may show as **No data**.

## Network Performance

The **Network Performance** section shows timing data that can help pinpoint where latency occurs.

* **Time to First Byte (TTFB)**: Measures the time between the initial request and the first byte of the response.
* **Time to Last Byte (TTLB) Breakdown**: Provides a breakdown of response phases:  
   * DNS resolution time  
   * TCP connection time  
   * Request processing time at the server  
   * Response transfer time

This breakdown helps identify whether delays are caused by DNS, connection setup, server processing, or response delivery.

## HTTP Traffic

The **HTTP Traffic** section shows how traffic is handled between Cloudflare and your origin server:

* **Served by**: Percentage of requests served from Cloudflare versus from your origin.
* **4xx errors**: Client errors, broken down by Cloudflare edge versus origin.
* **5xx errors**: Server errors, broken down by Cloudflare edge versus origin.

This view helps distinguish between Cloudflare-side issues and origin-side issues.

## Synthetic Monitoring

The **Synthetic Monitoring** table shows automated test results for your site. Each row includes:

* **URL tested**
* **Last test run**
* **Repeats** (if scheduled multiple times)
* **Score** (Pass/Fail)

Synthetic monitoring allows you to proactively test site availability and performance under consistent conditions, complementing real user monitoring (RUM).

## Using the dashboard

Use the Speed Overview dashboard to:

* Review **Suggestions** for actionable optimizations.
* Track **Core Web Vitals** to ensure a good user experience.
* Analyze **Network Performance** to identify latency bottlenecks.
* Diagnose errors with **HTTP Traffic** insights.
* Confirm site reliability using **Synthetic Monitoring** results.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/observatory/","name":"Observatory (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/observatory/dashboard/","name":"Observatory dashboard"}}]}
```

---

---
title: FAQ
description: Find answers to common questions about Cloudflare Observatory.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# FAQ

Below you will find answers to our most commonly asked questions. If you cannot find the answer you are looking for, refer to the [community page ↗](https://community.cloudflare.com/c/website-application-performance/88) to explore more resources.

## How long does it take for a test to load?

It can vary from about 25 seconds to over a minute. If you leave your speed tab open, your test is still going to run. You can leave and return and still see your test results.

## Are query parameters or anchors supported in tested URLs?

No. At the moment, any query parameter or anchor appended to the tested URL are dropped.

For example, using the `https://example.com/blog/?utm_medium=social#title` URL, the Observatory will discard the `?utm_medium=social` query parameter as well as the `#title` anchor. The tested URL will actually be `https://example.com/blog/`.

## I get a `403` response when rerunning the website analysis?

Check your WAF custom rules to make sure that you are not blocking traffic from Observatory to request your site.

Note

For **IPv6** Cloudflare Observatory tests originate from **ASN 15169** or **ASN 132892** and are generated with the following user agents:

* Mozilla/5.0 (Linux; Android 11; Moto G Power (2022)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Mobile Safari/537.36
* Mozilla/5.0 (Macintosh; Intel Mac OS X 10\_15\_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36

For **IPv4** Cloudflare Observatory tests originate from **ASN 396982** and are generated with the following user agents:

* Mozilla/5.0 (Linux; Android 11; moto g power (2022)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Mobile Safari/537.36 CloudflareObservatory/1.0
* Mozilla/5.0 (Macintosh; Intel Mac OS X 10\_15\_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 CloudflareObservatory/1.0

## Why might users not see any Real User Monitoring (RUM) data on the map in Observatory?

There are several reasons why users might not see any Real User Monitoring (RUM) data on the map in Observatory:

* Time Required for RUM Data Population: Populating the RUM database takes some time. It means that newly enabled RUM might not have immediate data available, and users may need to wait for some time before RUM data starts appearing on the map.
* Progressive Sampling: RUM data is progressively sampled, which means that not all requests are captured. Some requests may pass through the sampling period, resulting in incomplete or missing data points on the map.
* Adblockers Impact on RUM Data: RUM data collection relies on third-party JavaScript executing on the real-user browser. However, adblockers or similar browser extensions can block this script, preventing the collection of RUM data, and thereby affecting the completeness of the analytics presented on the map.
* The RUM feature needs to be enabled and configured in your environment. If it has not been turned on, or if configuration is incomplete, RUM data may not appear.

## What are the potential reasons for discrepancies between RUM analytics and traffic analytics in Observatory?

Differences between Real User Monitoring (RUM) analytics and traffic analytics in Observatory can occur due to the following reasons:

* Adblockers Impact on RUM Data: Similar to the previous point, RUM data collection can be thwarted by adblockers, leading to missed data. Since traffic analytics typically rely on server-side data collection, they may not be as affected by adblockers as RUM.
* Progressive Sampling in RUM: RUM data is collected through progressive sampling, which means that not all user requests are captured. This sampling method could result in slight variations in analytics when compared to traditional traffic analytics that record every server request.

## How do I disable Real User Monitoring (RUM) if it has been enabled from the Observatory test result page?

Enabling RUM creates a Web Analytics configuration entry for the hostname at the account level.

If you wish to disable RUM, follow these steps:

1. In the Cloudflare dashboard, go to the **Web Analytics** page.  
[ Go to **Web analytics** ](https://dash.cloudflare.com/?to=/:account/web-analytics)
2. Select **Manage Site** for the hostname for which you wish to disable RUM.
3. Select **Delete**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/observatory/","name":"Observatory (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/observatory/faq/","name":"FAQ"}}]}
```

---

---
title: RUM beacon for Web Analytics
description: Collect real user performance metrics with the RUM beacon.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# RUM beacon for Web Analytics

The RUM beacon is a JavaScript snippet that runs when a Cloudflare customer enables RUM through [Web Analytics](https://developers.cloudflare.com/web-analytics/) or [Observatory](https://developers.cloudflare.com/speed/observatory/). This script runs in users' browsers when they visit the customer's site, and its purpose is to collect performance-related data, for example, page load time, and send it to Cloudflare's systems for processing. This [data](https://developers.cloudflare.com/web-analytics/data-metrics/) is then presented to the customer, providing valuable insights into the website's performance and usage.

The RUM beacon script can be enabled into a webpage in two ways:

* **One-click setup**: For [sites proxied through Cloudflare](https://developers.cloudflare.com/web-analytics/get-started/#sites-proxied-through-cloudflare) that have Web Analytics enabled, the snippet can be _automatically_ injected into pages as the HTML response passes through Cloudflare's edge network to the browser by simply enabling the automatic injection option.
* **Manual setup**: Websites can _manually_ add the script by embedding a code snippet into their pages. Refer to the [Sites not proxied through Cloudflare section](https://developers.cloudflare.com/web-analytics/get-started/#sites-not-proxied-through-cloudflare), for more information about how to manually insert the snippet into your HTML.

## Data collection

Once downloaded to the browser, the RUM beacon script runs as JavaScript in the browser. It collects performance data from browser [APIs ↗](https://developer.mozilla.org/en-US/docs/Web/API/Performance%5FAPI) and sends this data to Cloudflare for processing.

The data collected from the browser is summarized in the table below:

| Field                | Example                                                                                                                | Description                                  | How it is collected                                                                                                                                                                                                                                                                                         |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| pageloadId           | 0c698922-8d60-40bf-85ac-7982b5f8034d                                                                                   | The unique ID for the page.                  | Generated in the browser code.                                                                                                                                                                                                                                                                              |
| referrer             | [https://cfrumtest.com/ ↗](https://cfrumtest.com/)                                                                     | The referring page URL.                      | If it is a multi-page application (MPA), then it is generated from [document.referrer ↗](https://developer.mozilla.org/en-US/docs/Web/API/Document/referrer). If it is a single-page application (SPA), then it is generated from a local in-memory variable in the beacon code which stores previous URLs. |
| startTime            | 1693488419352                                                                                                          | Baseline for performance-related timestamps. | [performance.timeOrigin ↗](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin)                                                                                                                                                                                                         |
| memory               | { totalJSHeapSize: 39973671, usedJSHeapSize: 39127515, jsHeapSizeLimit: 4294705152 }                                   | Measures memory heap size.                   | [performance.memory ↗](https://developer.mozilla.org/en-US/docs/Web/API/Performance/memory) (deprecated)                                                                                                                                                                                                    |
| timings              | Object of [PerformanceTiming ↗](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming)                    | Timing data.                                 | [performance.timing ↗](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timing) (deprecated, fallback when timingV2 is unavailable)                                                                                                                                                             |
| timingV2             | Array of [PerformanceNavigationTiming ↗](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming) | Navigation timing data.                      | [performance.getEntriesByType("navigation") ↗](https://developer.mozilla.org/en-US/docs/Web/API/Performance/getEntriesByType)                                                                                                                                                                               |
| resources            | Array of [PerformanceResourceTiming ↗](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming)     | Resource timing data.                        | [performance.getEntriesByType("resource") ↗](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming)                                                                                                                                                                                    |
| firstPaint           | Array of [PerformancePaintTiming ↗](https://developer.mozilla.org/en-US/docs/Web/API/PerformancePaintTiming)           | Paint timing data.                           | [performance.getEntriesByType("paint") ↗](https://developer.mozilla.org/en-US/docs/Web/API/PerformancePaintTiming)                                                                                                                                                                                          |
| firstContentfulPaint | 209                                                                                                                    | First Contentful Paint metric.               | [web-vitals module ↗](https://www.npmjs.com/package/web-vitals) [1](#user-content-fn-1)                                                                                                                                                                                                                     |
| FCP                  | 209                                                                                                                    | First Contentful Paint metric.               | [web-vitals module ↗](https://www.npmjs.com/package/web-vitals) [1](#user-content-fn-1)                                                                                                                                                                                                                     |
| LCP                  | 209                                                                                                                    | Largest Contentful Paint metric.             | [web-vitals module ↗](https://www.npmjs.com/package/web-vitals) [1](#user-content-fn-1)                                                                                                                                                                                                                     |
| CLS                  | 0.001                                                                                                                  | Cumulative Layout Shift metric.              | [web-vitals module ↗](https://www.npmjs.com/package/web-vitals) [1](#user-content-fn-1)                                                                                                                                                                                                                     |
| TTFB                 | 0.03                                                                                                                   | Time to First Byte metric.                   | [web-vitals module ↗](https://www.npmjs.com/package/web-vitals) [1](#user-content-fn-1)                                                                                                                                                                                                                     |
| INP                  | 1.23                                                                                                                   | Interaction to Next Paint metric.            | [web-vitals module ↗](https://www.npmjs.com/package/web-vitals) [1](#user-content-fn-1)                                                                                                                                                                                                                     |
| landingPath          | [https://cfrumtest.com/ ↗](https://cfrumtest.com/)                                                                     | The landing page URL.                        | [performance.getEntriesByType("navigation") ↗](https://developer.mozilla.org/en-US/docs/Web/API/Performance/getEntriesByType)                                                                                                                                                                               |

## Data processing

RUM data is generally processed at the nearest Cloudflare data center based on how the incoming request is routed. This is determined by a number of factors including [Anycast ↗](https://www.cloudflare.com/en-gb/learning/cdn/glossary/anycast-network/) and [Unimog ↗](https://blog.cloudflare.com/unimog-cloudflares-edge-load-balancer/). Since RUM data does not use location services, it may be processed in a different country or region from where it originated. Although the RUM service receives the client/source IP address from the beacon as part of normal HTTP request handling process, it discards the IP address at the nearest Cloudflare data center and does not store it in core databases or logs.

## Privacy information

The RUM beacon script does not store any data in the browser or access any storage data, such as [cookies ↗](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie), [localStorage ↗](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage), [sessionStorage ↗](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage), IP address, or [IndexedDB ↗](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB%5FAPI/Using%5FIndexedDB). The data we collect is performance data from the browser performance [APIs ↗](https://developer.mozilla.org/en-US/docs/Web/API/Performance%5FAPI). This performance data is ephemeral and only relates to the current webpage that is being viewed. If the user refreshes their browser, all the previous performance data is gone and new performance data starts being available. This data is not stored or accessed from anywhere on the device, it is only available as in-memory data.

## RUM excluding EEA/EU

Customers have the option to enable RUM globally or to limit its application to exclude users connecting to Cloudflare data centers in the EEA/EU. If the latter option is selected, the RUM beacon does not process performance data for users connecting to a Cloudflare data center located in the following countries (ISO codes): AT, BE, BG, HR, CY, CZ, DK, EE, FI, FR, DE, GR, HU, IS, IE, IT, LV, LI, LT, LU, MT, NL, NO, PL, PT, RO, SK, SI, ES, SE, CH, GB.

Free customers have RUM enabled automatically, with EU traffic excluded, and can switch it off if they prefer. Customers on other plans may enable RUM as needed.

![Enable RUM in the dashboard.](https://developers.cloudflare.com/_astro/enable-rum.BsPZ4NVP_Z4ELXQ.webp)

## Footnotes

1. The web-vitals module is an open-source module written by Google. It does not access any type of storage on the browser. [↩](#user-content-fnref-1) [↩2](#user-content-fnref-1-2) [↩3](#user-content-fnref-1-3) [↩4](#user-content-fnref-1-4) [↩5](#user-content-fnref-1-5) [↩6](#user-content-fnref-1-6)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/observatory/","name":"Observatory (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/observatory/rum-beacon/","name":"RUM beacon for Web Analytics"}}]}
```

---

---
title: Run test
description: Learn how to use Cloudflare's Observatory to assess the performance of your website.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Run test

## Run Synthetic test

1. In the Cloudflare dashboard, go to the **Synthetic Monitoring** page.  
[ Go to **Synthetic monitoring** ](https://dash.cloudflare.com/?to=/:account/:zone/speed/test)
2. Enter the URL you want to test. The URL must belong to the zone you are testing from.
3. Select the test type you want to use: **Browser** or **Network tests**.
4. Select the **Region** the automated browser will use.
5. Depending on your plan you can select to run the test **once**, **daily** or **weekly**. Refer to the [Quotas](https://developers.cloudflare.com/speed/observatory/run-speed-test/#quotas) section for information on the test frequency available for your plan. Note that these limits may change over time.
6. After the test finishes running, you will get a Lighthouse score and you will have access to the list of the tests run. The test result page will give you details regarding the performance of your website, both for the desktop and mobile versions. Refer to [Understand test results](https://developers.cloudflare.com/speed/observatory/test-results/) for more information.

Note

For **IPv6** Cloudflare Observatory tests originate from **ASN 15169** or **ASN 132892** and are generated with the following user agents:

* Mozilla/5.0 (Linux; Android 11; Moto G Power (2022)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Mobile Safari/537.36
* Mozilla/5.0 (Macintosh; Intel Mac OS X 10\_15\_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36

For **IPv4** Cloudflare Observatory tests originate from **ASN 396982** and are generated with the following user agents:

* Mozilla/5.0 (Linux; Android 11; moto g power (2022)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Mobile Safari/537.36 CloudflareObservatory/1.0
* Mozilla/5.0 (Macintosh; Intel Mac OS X 10\_15\_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 CloudflareObservatory/1.0

### Recommendations

Observatory shows you a **Recommendations** tab, depending on the results from testing your website. The **Recommendations** section shows you the opportunities to improve your website that were identified based on the Lighthouse audits and recommends Cloudflare features or products that will help you improve those metrics. We also show you the potential savings you will get by enabling the recommended features or products.

### Trend and History report

In the Tested URLs table, in the last column, you can select the three dots > **View history report**, and you will have access to the **Trend** table that will show your website’s performance metrics over time and a **History report** of all the tests you run on your website.

## Enable real user monitoring (RUM)

Once a test has been run, you can enable [RUM](https://developers.cloudflare.com/speed/observatory/#real-user-monitoring-rum) data in the test results page:

1. Go to **Observatory** and select **Enable RUM**. You can choose to enable globally or enable everywhere except the EU.
2. Once RUM data is running on your site, you can access **Real user measurements** on your test results page. Usually it takes less than five minutes to see the data coming in, but it will depend on traffic.

Refer to [Understand test results](https://developers.cloudflare.com/speed/observatory/test-results/) for more information about the results provided by real user data.

### Information collected

RUM uses a lightweight JavaScript beacon to collect the information Observatory uses. It does not use any client-side state, such as cookies or `localStorage`, to collect usage metrics.

## Quotas

Quota limits for the number of tests you can run per month are currently the following:

| Plan       | One-off tests | Recurring tests | Frequency of recurring tests |
| ---------- | ------------- | --------------- | ---------------------------- |
| Pro        | 50            | 5               | Daily                        |
| Business   | 100           | 10              | Daily                        |
| Enterprise | 150           | 15              | Daily                        |

**Available Regions (all plans):**

| Region              | Region                 | Region                  |
| ------------------- | ---------------------- | ----------------------- |
| Iowa, USA           | Hamina, Finland        | Changhua County, Taiwan |
| South Carolina, USA | Madrid, Spain          | Tokyo, Japan            |
| North Virginia, USA | St. Ghislain, Belgium  | Osaka, Japan            |
| Dallas, USA         | Eemshaven, Netherlands | Jurong West, Singapore  |
| Oregon, USA         | Milan, Italy           | Sydney, Australia       |
| London, England     | Paris, France          | Mumbai, India           |
| Frankfurt, Germany  | Tel Aviv, Israel       | São Paulo, Brazil       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/observatory/","name":"Observatory (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/observatory/run-speed-test/","name":"Run test"}}]}
```

---

---
title: Understand test results
description: Interpret Lighthouse scores and Core Web Vitals from Observatory tests.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Understand test results

The test result page shows you how your website performed regarding several key industry metrics. Some of these metrics are presented for synthetic tests and the real user monitoring, and others only apply to synthetic tests or only to real user monitoring.

## Synthetic tests and real user monitoring metrics

These metrics are presented for the synthetic tests and they are also collected as part of the real user data.

| Metric                                                                    | Definition                                                                                                                            |
| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| Time to First Byte ([TTFB ↗](https://web.dev/ttfb/))                      | Measures the time between the request for a resource and when the first byte of a response begins to arrive.                          |
| First Contentful Paint ([FCP ↗](https://web.dev/first-contentful-paint/)) | Measures the time from when the page starts loading to when any part of the page's content is rendered on the screen.                 |
| Largest Contentful Paint ([LCP ↗](https://web.dev/lcp/))                  | CP reports the render time of the largest image or text block visible within the viewport.                                            |
| Cumulative Layout Shift ([CLS ↗](https://web.dev/cls/))                   | Measures the largest burst of layout shift scores for every unexpected layout shift that occurs during the entire lifespan of a page. |

## Synthetic tests metrics

These metrics result from the synthetic tests.

| Metric                                              | Definition                                                                                                                                                                              |
| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Time to Interactive ([TTI ↗](https://web.dev/tti/)) | Measures the time from when the page starts loading to when its main sub-resources have loaded and it is capable of reliably responding to user input quickly.                          |
| Total Blocking Time ([TBT ↗](https://web.dev/tbt/)) | Measures the total amount of time between First Contentful Paint (FCP) and Time to Interactive (TTI) where the main thread was blocked for long enough to prevent input responsiveness. |
| [Speed index ↗](https://web.dev/speed-index/)       | Measures how quickly content is visually displayed during page load.                                                                                                                    |

## Real user monitoring metrics

These metrics are collected as part of the real user data, as they require real user interaction with a page.

| Metric                                                    | Definition                                                                                                                 |
| --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| Interaction to Next Paint ([INP ↗](https://web.dev/inp/)) | Aims to represent a page's overall responsiveness by measuring all click, tap, and keyboard interactions made with a page. |

Refer to [Data and metrics](https://developers.cloudflare.com/web-analytics/data-metrics/) for more information about the metrics you can find in the Real User Monitoring dashboard. You can find details about [Core Web Vitals](https://developers.cloudflare.com/web-analytics/data-metrics/core-web-vitals/), the debug view and the data collected.

## Network monitoring metrics

| Metric                                                       | Definition                                                                                                        |
| ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- |
| Wait Time                                                    | Measures the time spent waiting for the server to send back the first byte of a response after a request is made. |
| Load Time                                                    | Measures the total time it takes for a web page to fully load in a user’s browser from the network.               |
| Time to First Byte ([TTFB ↗](https://web.dev/articles/ttfb)) | Measures the duration between initiating a web page request and receiving the first byte from the server.         |
| Server Response Time                                         | Measures the time it takes for a server to respond to a request from a user's browser.                            |
| Connect Time                                                 | Measures the time taken to establish a connection between the user's browser and the web server.                  |
| TLS Time                                                     | Measures the time required to complete the TLS/SSL handshake between the user's browser and the web server.       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/observatory/","name":"Observatory (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/observatory/test-results/","name":"Understand test results"}}]}
```

---

---
title: Cloudflare Smart Shield
description: Use Smart Shield to protect your origin server, improve content availability, and reduce network latency.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare Smart Shield

Protect your origin server, reduce load, and improve content delivery performance.

Every request that reaches your origin server costs resources — bandwidth, compute, and connections. When traffic spikes or your content is requested from many locations simultaneously, your origin can become a bottleneck. Smart Shield is a bundle of origin protection and performance features that reduce the number of requests and connections between Cloudflare's network and your origin server.

Smart Shield includes [Smart Tiered Cache](https://developers.cloudflare.com/smart-shield/configuration/smart-tiered-cache/), which organizes Cloudflare data centers into upper-tier and lower-tier groups so that only upper-tier data centers contact your origin for uncached content. Combined with [connection reuse](https://developers.cloudflare.com/smart-shield/concepts/connection-reuse/), which packages multiple requests into a single connection to your origin, Smart Shield reduces both the volume of origin requests and the number of open connections.

Depending on your [package tier](https://developers.cloudflare.com/smart-shield/get-started/#packages-and-availability), Smart Shield can also include:

* [Argo Smart Routing](https://developers.cloudflare.com/smart-shield/configuration/argo/) — routes traffic through the fastest network paths to reduce latency.
* [Regional Tiered Cache](https://developers.cloudflare.com/smart-shield/configuration/regional-tiered-cache/) — adds a regional cache layer between lower-tier and upper-tier data centers for geographic data locality (Enterprise plans, or Smart Shield Advanced).
* [Cache Reserve](https://developers.cloudflare.com/smart-shield/configuration/cache-reserve/) — persistent cache storage that reduces cache misses for infrequently accessed content.
* [Health Checks](https://developers.cloudflare.com/smart-shield/configuration/health-checks/) — monitors your origin server availability (Pro plans and above).
* [Dedicated CDN Egress IPs](https://developers.cloudflare.com/smart-shield/configuration/dedicated-egress-ips/) — reserved IP addresses for origin allowlisting (Enterprise).

For a visual overview of how these features work together, refer to the [network diagram](https://developers.cloudflare.com/smart-shield/concepts/network-diagram/).

Learn how to [get started](https://developers.cloudflare.com/smart-shield/get-started/).

---

## Related products

**[Cache](https://developers.cloudflare.com/cache/)** 

Cache stores copies of frequently accessed content (such as images, videos, or webpages) in geographically distributed data centers that are located closer to end users than origin servers, improving website performance.

**[Observatory](https://developers.cloudflare.com/speed/observatory/)** 

Observatory uses synthetic tests and real user data to assess the performance of your website, producing different metrics and insights. Cloudflare then uses this analysis to recommend optimizations that best address your performance issues.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/smart-shield/","name":"Smart Shield"}}]}
```

---

---
title: Troubleshooting
description: Troubleshoot common speed and performance optimization issues.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

The following topics are useful for troubleshooting Speed issues.

Filter resources...

[FAQ](https://developers.cloudflare.com/speed/observatory/faq/)[FAQ | Cloudflare Fonts](https://developers.cloudflare.com/speed/optimization/content/fonts/faq/)[Cloudflare Fonts troubleshooting](https://developers.cloudflare.com/speed/optimization/content/fonts/troubleshooting/)[Content encoding issues](https://developers.cloudflare.com/speed/optimization/content/troubleshooting/content-encoding-issues/)[Turn off Auto Minify via API](https://developers.cloudflare.com/speed/optimization/content/troubleshooting/disable-auto-minify/)[Image optimization on optimized images](https://developers.cloudflare.com/speed/optimization/images/troubleshooting/multiple-optimizations/)[Troubleshoot missing images](https://developers.cloudflare.com/speed/optimization/images/troubleshooting/troubleshooting-missing-images/)[Enhanced HTTP/2 Prioritization negatively affects iOS/Safari devices](https://developers.cloudflare.com/speed/optimization/protocol/troubleshooting/enhanced-http2-prioritization-ios-safari/)[Troubleshoot protocol issues](https://developers.cloudflare.com/speed/optimization/protocol/troubleshooting/protocol-troubleshooting/)[Troubleshooting a slow website](https://developers.cloudflare.com/speed/troubleshooting/slow-website/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: Troubleshooting a slow website
description: Identify and resolve performance issues affecting your website.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting a slow website

This guide helps you identify and resolve performance issues affecting your website. It starts with basic diagnostics and progresses to advanced troubleshooting techniques.

## Before you start: Verify traffic goes through Cloudflare

Before troubleshooting performance, confirm that your traffic is actually going through Cloudflare. If requests bypass Cloudflare, the issue is not related to Cloudflare and this guide will not help.

### Check for the cf-ray header

Every response served through Cloudflare includes a `cf-ray` header. Check for this header:

* [ bash ](#tab-panel-10409)
* [ PowerShell ](#tab-panel-10410)

Terminal window

```

curl -s -D- -o /dev/null https://www.example.com | grep -i cf-ray


```

PowerShell

```

(Invoke-WebRequest -Uri "https://www.example.com" -Method Head).Headers["cf-ray"]


```

If you see a `cf-ray` header (for example, `cf-ray: 8a1b2c3d4e5f6g7h-SJC`), your traffic is going through Cloudflare. If not, check your DNS configuration.

### Verify DNS is pointing to Cloudflare

Your domain must resolve to Cloudflare IP addresses for traffic to be proxied:

* [ bash ](#tab-panel-10411)
* [ PowerShell ](#tab-panel-10412)

Terminal window

```

dig +short www.example.com


```

PowerShell

```

Resolve-DnsName -Name www.example.com | Select-Object -ExpandProperty IPAddress


```

The returned IP addresses should be [Cloudflare IPs ↗](https://www.cloudflare.com/ips/). If they point directly to your origin server, your DNS records are not proxied.

To fix this:

1. Go to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/?to=/:account/:zone/dns).
2. Find the DNS record for the slow hostname.
3. Ensure the **Proxy status** is set to **Proxied** (orange cloud icon).

Note

If your DNS records are set to **DNS only** (gray cloud), Cloudflare does not proxy the traffic and cannot improve performance. The request goes directly to your origin server.

---

## Gather information about the slow requests

Performance issues are easier to solve when you can pinpoint exactly what is slow. Start by gathering the following information:

1. **Identify specific slow requests** \- Determine which URLs, assets, or API endpoints are slow.
2. **Measure the slowness** \- Quantify the delay (for example, "this image takes 5 seconds to load").
3. **Reproduce the issue** \- Confirm the slowness is consistent and not a one-time occurrence.

---

## Step 1: Use Observatory to analyze performance

[Observatory](https://developers.cloudflare.com/speed/observatory/) provides synthetic tests and real user monitoring (RUM) data to assess your website's performance.

RUM is particularly important as these metrics are captured from your actual visitors' browsers so it's an objective view of how they are experiencing your website, rather than lab data, which is typically more detailed (useful for debugging) but doesn't always correlate with the devices or connectivity real people have access to.

### Run a speed test

1. Go to the Cloudflare dashboard.  
[ Go to **Observatory** ](https://dash.cloudflare.com/?to=/:account/:zone/speed)
2. Select **Observatory**.
3. Enter the URL you want to test and select **Run test**.

### Understand the results

Observatory reports key metrics:

| Metric                             | What it measures                                  | Target            |
| ---------------------------------- | ------------------------------------------------- | ----------------- |
| **Largest Contentful Paint (LCP)** | Time until the largest visible element loads      | Under 2.5 seconds |
| **First Contentful Paint (FCP)**   | Time until the first content appears              | Under 1.8 seconds |
| **Cumulative Layout Shift (CLS)**  | Visual stability during page load                 | Under 0.1         |
| **Time to First Byte (TTFB)**      | Time until the first byte of response is received | Under 800 ms      |
| **Total Blocking Time (TBT)**      | Time the main thread is blocked                   | Under 200 ms      |

Real User Monitoring reports similar metrics but you'll see Interaction to Next Paint (INP) in place of Total Blocking Time (TBT).

TBT only measures during page load but INP measures every interaction real visitors make with your website.

### Enable recommended optimizations

Based on Observatory results, enable relevant [Speed optimizations](https://developers.cloudflare.com/speed/optimization/):

* [Brotli compression](https://developers.cloudflare.com/speed/optimization/content/compression/) \- Compress responses for faster transfer
* [Early Hints](https://developers.cloudflare.com/cache/advanced-configuration/early-hints/) \- Preload critical resources
* [HTTP/2 and HTTP/3](https://developers.cloudflare.com/speed/optimization/protocol/) \- Use modern protocols with multiplexing, allowing multiple requests over a single connection instead of opening separate connections for each asset
* [Image optimization](https://developers.cloudflare.com/images/) \- Automatically optimize and resize images
* [Rocket Loader](https://developers.cloudflare.com/speed/optimization/content/rocket-loader/) \- Defer loading of JavaScript to improve paint times

---

## Step 2: Identify slow resources

If Observatory and RUM data point to specific issues, use browser developer tools to investigate individual resources.

### Use browser developer tools

1. Open your browser's developer tools.
2. Go to the **Network** tab.
3. Reload the page and observe which requests take the longest.
4. Sort by **Time** or **Duration** to identify the slowest assets.
5. Note the specific URLs of slow resources.

Look for:

* Large images or videos
* Slow API calls
* Third-party scripts
* Render-blocking resources

---

## Step 3: Analyze origin performance

If your website is slow, the issue may be at your origin server. Use Origin Analytics to understand how your origin is performing.

### Check origin response times

In the Cloudflare dashboard:

1. Go to **Speed** \> **Origin Analytics**.
2. Review the **Origin Response Time** metrics.
3. Look for patterns in slow responses (specific paths, times of day, or geographic regions).

High origin response times indicate your origin server is struggling. Consider:

* Upgrading your hosting plan
* Optimizing database queries
* Implementing server-side caching

### Check for slow Workers

If your zone has [Cloudflare Workers](https://developers.cloudflare.com/workers/) deployed, they execute on every matching request and add to the total response time. A slow Worker is a common cause of high TTFB.

To check if Workers are affecting performance:

1. Go to **Workers & Pages** in the Cloudflare dashboard.
2. Review which Workers are deployed on your zone.
3. Check the **Analytics** for each Worker to see execution times.
4. Temporarily disable Workers to isolate whether they are causing the slowness.

If a Worker is slow, review its code for:

* Slow external API calls or `fetch()` requests
* Inefficient loops or data processing
* Missing `await` statements causing sequential instead of parallel execution

---

## Step 4: Measure performance from the command line

For detailed timing metrics on specific requests, use command-line tools to measure performance.

### Basic performance test

* [ bash ](#tab-panel-10413)
* [ PowerShell ](#tab-panel-10414)

Terminal window

```

curl -w "\n\nDNS Lookup: %{time_namelookup}s\nTCP Connect: %{time_connect}s\nTLS Handshake: %{time_appconnect}s\nTime to First Byte: %{time_starttransfer}s\nTotal Time: %{time_total}s\n" -o /dev/null -s https://www.example.com/slow-asset.jpg


```

PowerShell

```

$url = "https://www.example.com/slow-asset.jpg"

try {

    $timing = Measure-Command {

        $response = Invoke-WebRequest -Uri $url -ErrorAction Stop

    }

    Write-Host "Total Time: $($timing.TotalSeconds)s"

    Write-Host "Status: $($response.StatusCode)"

} catch {

    if ($_.Exception.Response) {

        $statusCode = $_.Exception.Response.StatusCode.value__

        Write-Host "Error Status: $statusCode"

    }

    Write-Host "Error: $($_.Exception.Message)"

}


```

Example output (bash):

```

DNS Lookup: 0.025s

TCP Connect: 0.045s

TLS Handshake: 0.120s

Time to First Byte: 0.350s

Total Time: 1.250s


```

### Understand the metrics

The curl timing breakdown shows the following:

| Metric                        | Description                          | High value indicates                    |
| ----------------------------- | ------------------------------------ | --------------------------------------- |
| **DNS Lookup**                | Time to resolve the domain name      | DNS issues or slow resolver             |
| **TCP Connect**               | Time to establish TCP connection     | Network latency or server distance      |
| **TLS Handshake**             | Time to complete SSL/TLS negotiation | Certificate chain issues or slow server |
| **Time to First Byte (TTFB)** | Time until first response byte       | Slow origin processing                  |
| **Total Time**                | Complete request duration            | Large file size or slow transfer        |

### Test from different locations

To test from different geographic locations, use online tools like:

* [KeyCDN Tools ↗](https://tools.keycdn.com/performance)
* [Uptrends ↗](https://www.uptrends.com/tools/website-speed-test)
* [Dotcom-Tools ↗](https://www.dotcom-tools.com/website-speed-test)

---

## Step 5: Investigate caching

Caching is one of the most effective ways to improve website performance. When content is cached, Cloudflare serves it directly from a data center close to your visitors, eliminating the round trip to your origin server. This can reduce response times from hundreds of milliseconds to just a few milliseconds.

Uncached content must travel from the visitor to Cloudflare, then to your origin server, and back again. Use [Cache Analytics](https://developers.cloudflare.com/cache/performance-review/cache-analytics/) to understand your cache performance and identify opportunities to cache more content.

### Check if assets are cached

Check the cache status of a specific asset:

* [ bash ](#tab-panel-10415)
* [ PowerShell ](#tab-panel-10416)

Terminal window

```

curl -s -D- -o /dev/null https://www.example.com/asset.jpg | grep -i "cf-cache-status"


```

PowerShell

```

(Invoke-WebRequest -Uri "https://www.example.com/asset.jpg" -Method Head).Headers["cf-cache-status"]


```

Possible values:

| Status          | Meaning                                 | Action                        |
| --------------- | --------------------------------------- | ----------------------------- |
| **HIT**         | Served from Cloudflare cache            | No action needed              |
| **MISS**        | Not in cache, fetched from origin       | May need cache rules          |
| **DYNAMIC**     | Not eligible for caching                | Create a cache rule if static |
| **BYPASS**      | Cache intentionally bypassed            | Review cache rules            |
| **EXPIRED**     | Cached copy was stale                   | Increase Edge TTL             |
| **REVALIDATED** | Cloudflare confirmed content is current | Increase Edge TTL             |

For a complete list, refer to [Cloudflare cache responses](https://developers.cloudflare.com/cache/concepts/cache-responses/).

### Use Cache Analytics

1. Go to the Cloudflare dashboard.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/caching)
2. Review the **Cache Performance** section.
3. Filter by **Cache status equals MISS** or **DYNAMIC** to identify uncached content.

### Investigate why static content is not cached

If static assets (images, CSS, JavaScript) show a cache status of `DYNAMIC`, `BYPASS`, or `MISS`, investigate the cause:

| Symptom                 | Likely cause                                                                                                                                           | Solution                                                                                                                                                                                                                  |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DYNAMIC status          | Content type not in [default file extensions](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#default-cached-file-extensions) | Create a Cache Rule to cache the content                                                                                                                                                                                  |
| DYNAMIC status          | Origin sends Cache-Control: private or no-store                                                                                                        | Create a Cache Rule to [override origin cache control](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#origin-cache-control)                                                                         |
| BYPASS status           | A Cache Rule is bypassing cache                                                                                                                        | Review your [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/) configuration                                                                                                                      |
| MISS on every request   | Response includes Set-Cookie header                                                                                                                    | Configure your origin to not set cookies on static assets, or use a Cache Rule to [ignore cookies](https://developers.cloudflare.com/cache/concepts/cache-behavior/#interaction-of-set-cookie-response-header-with-cache) |
| MISS with query strings | Different query strings create different cache entries                                                                                                 | Use a [custom cache key](https://developers.cloudflare.com/cache/how-to/cache-rules/examples/custom-cache-key/) to ignore or normalize query strings                                                                      |

### Cache additional static content

By default, Cloudflare only caches certain [file extensions](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#default-cached-file-extensions). To cache additional static content:

1. Go to **Caching** \> **Cache Rules**.
2. Create a rule to [cache specific content](https://developers.cloudflare.com/cache/how-to/cache-rules/examples/cache-everything/).
3. Set appropriate [Edge TTLs](https://developers.cloudflare.com/cache/how-to/cache-rules/settings/#edge-ttl).

Warning

Be careful when caching HTML or API responses. These often contain personalized or dynamic content that should not be cached. Only cache content you are certain is static.

### Use Cloudflare Trace to debug cache rules

If your cache rules are not applying as expected, use [Cloudflare Trace](https://developers.cloudflare.com/rules/trace-request/) to simulate a request and see exactly which rules match. Trace shows you how your Cloudflare configurations (including cache rules, page rules, and other settings) would affect a specific URL.

This is particularly useful when:

* A cache rule should be caching content but the response shows `DYNAMIC` or `BYPASS`
* You are unsure which rule is taking precedence
* You want to test a "what-if" scenario before making changes

---

## Step 6: Diagnose network issues

If curl shows high TCP Connect or TLS Handshake times, the issue may be network-related rather than application-related.

### Test your Internet connection

Visit [speed.cloudflare.com ↗](https://speed.cloudflare.com) to test:

* Download and upload speeds
* Latency (ping)
* Jitter
* Packet loss

Poor results indicate issues with your local network or ISP.

### Run MTR from your location to Cloudflare

MTR combines traceroute and ping to show latency and packet loss at each network hop.

* [ macOS/Linux ](#tab-panel-10417)
* [ Windows ](#tab-panel-10418)

Terminal window

```

mtr -rw www.example.com


```

Download [WinMTR ↗](https://github.com/White-Tiger/WinMTR/releases) and run it with your domain as the target.

Look for:

* **High latency** at specific hops (indicates slow network segments)
* **Packet loss** (indicates network congestion or issues)
* **Timeouts** (may indicate firewalls or routing issues)

For more details, refer to [How to read MTR ↗](https://www.cloudflare.com/learning/network-layer/what-is-mtr/).

### Run MTR from your origin to Cloudflare

If you have access to your origin server, run MTR from the origin to a [Cloudflare IP address ↗](https://www.cloudflare.com/ips/) to test the network path between your origin and Cloudflare.

Terminal window

```

mtr -rw 104.16.132.229


```

High latency or packet loss on this path affects all requests that miss the cache.

---

## Step 7: Understand network routing

How requests are routed to Cloudflare data centers can significantly impact performance.

### Identify which data center serves your requests

Add `/cdn-cgi/trace` to your domain to see which Cloudflare data center is serving your requests:

* [ bash ](#tab-panel-10419)
* [ PowerShell ](#tab-panel-10420)

Terminal window

```

curl https://www.example.com/cdn-cgi/trace


```

PowerShell

```

Invoke-RestMethod -Uri "https://www.example.com/cdn-cgi/trace"


```

The `colo` field shows the three-letter airport code of the serving data center (for example, `colo=SJC` for San Jose). You can find the full list of Cloudflare data centers and their codes on the [Cloudflare status page ↗](https://www.cloudflarestatus.com/).

### Why routing matters

When a request reaches Cloudflare:

1. The request is routed to a nearby Cloudflare data center based on anycast [routing ↗](https://www.cloudflare.com/learning/cdn/glossary/anycast-network/).
2. If the content is cached, it is served immediately.
3. If not cached, Cloudflare fetches from your origin server.

If your origin server is geographically distant from the Cloudflare data center serving your users, uncached requests will be slow.

### Troubleshoot unexpected routing

If requests are being routed to a data center that seems far from the user, this may be due to Cloudflare's automated traffic engineering or a user’s ISP routing traffic.

While Cloudflare always strives to provide the best possible performance by serving traffic from the closest location, reliability is the top priority. In instances where performance and reliability are in conflict, Cloudflare's systems are designed to prioritize a stable connection over a local one.

For more details, refer to [Cloudflare traffic not being sent to the geographically closest data center](https://developers.cloudflare.com/support/troubleshooting/general-troubleshooting/geographic-traffic-routing/).

Common causes of unexpected routing:

| Symptom                                 | Explanation                                                                  |
| --------------------------------------- | ---------------------------------------------------------------------------- |
| Requests route to a distant data center | Cloudflare traffic engineering for reliability, or ISP routing decisions     |
| Routing changes between requests        | Normal behavior - routing adapts to network conditions or ISP load balancing |
| Consistent routing to a distant region  | ISP peering location or Cloudflare capacity management                       |
| High latency despite nearby data center | Network congestion on the path                                               |

### Solutions for origin distance

Consider these solutions based on your needs:

| Solution                                                                         | Description                                           | Best for                           |
| -------------------------------------------------------------------------------- | ----------------------------------------------------- | ---------------------------------- |
| **Improve cache hit ratio**                                                      | Cache more content to reduce origin fetches           | All sites                          |
| **[Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/)** | Use upper-tier data centers to reduce origin requests | Sites with global traffic          |
| **[Argo Smart Routing](https://developers.cloudflare.com/argo-smart-routing/)**  | Route traffic over faster network paths               | Sites with slow origin connections |
| **Move origin closer**                                                           | Deploy origin servers in multiple regions             | Large-scale applications           |

### Enable Argo Smart Routing

[Argo Smart Routing](https://developers.cloudflare.com/argo-smart-routing/) analyzes network conditions in real-time and routes traffic over the fastest paths, reducing latency by an average of 30%.

Argo Smart Routing is part of [Smart Shield](https://developers.cloudflare.com/smart-shield/), which bundles multiple Cloudflare performance and reliability features.

To enable Argo Smart Routing:

1. Go to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/?to=/:account/:zone/smart-shield).
2. Follow the [Smart Shield setup guide](https://developers.cloudflare.com/smart-shield/get-started/) to enable the feature.

Argo is particularly effective when:

* Your origin is far from your users
* Network congestion affects certain paths
* You need consistent performance globally

For detailed information about how Argo Smart Routing works, refer to the [Argo Smart Routing documentation](https://developers.cloudflare.com/argo-smart-routing/).

---

## Contact Support if the problem persists

If you have followed the steps above and the performance issue persists, [contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) for assistance.

When contacting Support, provide as much evidence as possible to help diagnose the issue:

* **HAR file** \- [Generate a HAR file](https://developers.cloudflare.com/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/#generate-a-har-file) that captures the slow requests. This provides detailed timing information for every request.
* **Observatory results** \- Share screenshots or links to your Observatory test results.
* **RUM data** \- If you have Web Analytics enabled, share relevant metrics showing the performance issue.
* **curl output** \- Include the timing breakdown from `curl --write-out` for the slow assets.
* **MTR results** \- If you suspect network issues, include MTR output from your location to the affected domain.
* **Specific URLs** \- List the exact URLs that are slow, along with the expected and actual response times.

The more evidence you provide showing the slowness, the faster Support can identify and resolve the issue.

---

## Related resources

* [Observatory](https://developers.cloudflare.com/speed/observatory/) \- Test and monitor website performance
* [Cache Analytics](https://developers.cloudflare.com/cache/performance-review/cache-analytics/) \- Analyze cache hit rates
* [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/) \- Control what gets cached
* [Argo Smart Routing](https://developers.cloudflare.com/argo-smart-routing/) \- Optimize network routing
* [Gathering information for troubleshooting](https://developers.cloudflare.com/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/) \- Collect diagnostic data

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/troubleshooting/slow-website/","name":"Troubleshooting a slow website"}}]}
```

---

---
title: Aggregated Internet Measurement
description: Measure real-world internet quality metrics for your visitors.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Aggregated Internet Measurement

Aggregated Internet Measurement (AIM) helps you understand your Internet quality to identify scenarios that your Internet connection is good or bad for. Typically, an Internet speed test provides you with upload and download speeds, which may not always provide a holistic view of your Internet quality.

AIM uses a scoring rubric that assigns point values based on speed tests to help you understand how your Internet quality will perform for streaming, gaming, and webchat/real-time communication (RTC).

## Scoring Rubric

AIM analyzes the following metrics to generate your score:

* Latency
* Packet Loss
* Download
* Upload
* Loaded Latency
* Jitter

After the test is run and a point value is assigned to each metric, the points are translated to a network score for streaming, gaming, and webchat/RTC. These scores will indicate how good your Internet is in each of these scenarios.

The possible network scores are:

* Bad
* Poor
* Average
* Good
* Great

## Improve your network score

You have a few options to help improve network scores.

* **Switch to a wired connection.** When possible, switch to a wired connection instead of wireless to avoid performance issues due to radio interference and signal strength.
* **Move closer to your router.** If you are unable to use a wired connection, try to move closer to your wireless router. Signal strength drops as you move away from your wireless router and a weaker signal means poorer connectivity. Keep in mind that any objects or materials between you and your wireless router can also have a negative impact on signal strength.
* **Upgrade your router.** Ensure you are using a router capable of handling smarter queueing with hardware that will not fall over under load.
* **Contact your ISP.** If you’re using a wired connection or have a good connection to your wireless router and are still seeing issues, you may have issues with your Internet connection and should reach out to your ISP.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/aim/","name":"Aggregated Internet Measurement"}}]}
```

---

---
title: Glossary
description: Definitions for terms used across Cloudflare Speed documentation.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Glossary

Review the definitions for terms used across Cloudflare's Speed documentation.

| Term                             | Definition                                                                                                                                                                                                                                                                    |
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| bandwidth                        | The maximum rate of data transfer across a network.                                                                                                                                                                                                                           |
| brotli compression               | Brotli compression is a data compression algorithm developed by Google, optimized for web content, and designed to achieve higher compression ratios than traditional algorithms like Gzip.                                                                                   |
| compression                      | The process of reducing the size of files or data to speed up their transfer over the network.                                                                                                                                                                                |
| core web vitals                  | Core web vitals are a set of user-centric performance metrics, including Largest Contentful Paint (LCP), Cumulative Layout Shift (CLS), and First Input Delay (FID), used by Google to assess the overall user experience of a webpage.                                       |
| cumulative layout shift (CLS)    | Cumulative layout shift (CLS) is a web performance metric that quantifies the visual stability of a webpage by measuring the sum of unexpected layout shifts of elements during the page's loading and rendering process.                                                     |
| first contentful paint (FCP)     | First contentful paint (FCP) is a web performance metric that measures the time it takes for the first piece of content to be rendered on the screen during the loading of a web page.                                                                                        |
| first input delay (FID)          | First input delay (FID) is a web performance metric that measures the delay between a user's first interaction with a page (for example, clicking a button) and the moment the browser responds, indicating the page's interactivity and responsiveness.                      |
| interaction to next paint (INP)  | Interaction to next paint (INP) is a web performance metric that measures the time it takes for a web page to become interactive and respond to user input after the initial paint, providing insights into the user experience during the interaction phase of page loading. |
| largest contentful paint (LCP)   | Largest contentful paint (LCP) is a web performance metric that measures the time it takes for the largest content element to be fully rendered and visible to the user during the loading of a web page.                                                                     |
| latency                          | The delay between a user action and the corresponding response from the system.                                                                                                                                                                                               |
| lazy loading                     | Loading images or other resources only when they are about to be displayed, rather than loading everything at once.                                                                                                                                                           |
| minification                     | The process of removing unnecessary characters from code (such as whitespace or comments) to reduce file size and improve loading times.                                                                                                                                      |
| page load time                   | The time it takes for a web page to fully load in a user's browser.                                                                                                                                                                                                           |
| real user monitoring (RUM)       | Real user monitoring (RUM) is a web performance monitoring technique that collects and analyzes data based on actual user interactions and experiences, providing insights into how users interact with a website or application in real-time.                                |
| render time                      | The time it takes for a browser to display a fully rendered web page after receiving the necessary resources.                                                                                                                                                                 |
| search engine optimization (SEO) | SEO, or search engine optimization, is the practice of optimizing online content to improve its visibility and ranking in search engine results, thereby increasing organic traffic and relevance.                                                                            |
| server response time             | The time it takes for a server to respond to a request from a user's browser.                                                                                                                                                                                                 |
| speed index                      | Speed index is a web performance metric that quantifies how quickly a user perceives a webpage to load by measuring the visual progression of content rendering over time, providing a comprehensive assessment of the overall user experience during page loading.           |
| synthetic test                   | A synthetic test is an artificial simulation of user interactions and system behaviors designed to evaluate and measure the performance, responsiveness, and functionality of a website or application under controlled conditions.                                           |
| time to first byte (TTFB)        | Time to first byte (TTFB) is the duration measured from the initiation of a web page request to the moment the first byte of data is received by the user's browser from the web server, indicating the server's initial response time.                                       |
| time to interactive (TTI)        | Time to interactive (TTI) is a web performance metric that measures the time it takes for a web page to become fully interactive and responsive to user input, indicating when users can effectively engage with and use the page.                                            |
| total blocking time (TBT)        | Total blocking time (TBT) is a web performance metric that measures the total amount of time between First Contentful Paint (FCP) and Time to Interactive (TTI) where the main thread was blocked for long enough to prevent input responsiveness.                            |

View more terms 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/glossary/","name":"Glossary"}}]}
```

---

---
title: Automatic Platform Optimization
description: Cache and serve your entire WordPress site from the Cloudflare edge network.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Automatic Platform Optimization

Take your WordPress site’s performance to the next level with Automatic Platform Optimizations (APO). APO allows Cloudflare to serve your entire WordPress site from its edge network ensuring consistent, fast performance for visitors no matter where they are.

Automatic Platform Optimization is the result of using the power of [Cloudflare Workers](https://developers.cloudflare.com/workers/) to intelligently cache dynamic content. By caching dynamic content, Cloudflare can serve the entire website from our edge network to make a site's time to first byte (TTFB) both fast and consistent.

To read more about the benefits of using APO with your site, see [The Benefits of Automatic Platform Optimization blog ↗](https://blog.cloudflare.com/automatic-platform-optimizations-starting-with-wordpress/#the-benefits-of-automatic-platform-optimization). You must use the Cloudflare for WordPress plugin to begin using APO.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/automatic-platform-optimization/","name":"Automatic Platform Optimization"}}]}
```

---

---
title: Content compression
description: Learn how Cloudflare compresses content for faster web performance.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Content compression

Cloudflare compresses content in two ways: between Cloudflare and your website visitors and between Cloudflare and your origin server.

## Compression between Cloudflare and website visitors

In addition to Cloudflare's [default caching behavior](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/), Cloudflare supports Gzip, Brotli, and Zstandard compression when delivering content to website visitors.

Note

Customers can enable Zstandard compression through [Compression Rules](https://developers.cloudflare.com/rules/compression-rules/).

If supported by visitors' web browsers, Cloudflare will return Gzip, Brotli, or Zstandard-encoded responses for the following content types:

```

text/html

text/richtext

text/plain

text/css

text/x-script

text/x-component

text/x-java-source

text/x-markdown

application/javascript

application/x-javascript

text/javascript

text/js

image/x-icon

image/vnd.microsoft.icon

application/x-perl

application/x-httpd-cgi

text/xml

application/xml

application/rss+xml

application/vnd.api+json

application/x-protobuf

application/json

multipart/bag

multipart/mixed

application/xhtml+xml

font/ttf

font/otf

font/x-woff

image/svg+xml

application/vnd.ms-fontobject

application/ttf

application/x-ttf

application/otf

application/x-otf

application/truetype

application/opentype

application/x-opentype

application/font-woff

application/eot

application/font

application/font-sfnt

application/wasm

application/javascript-binast

application/manifest+json

application/ld+json

application/graphql+json

application/geo+json


```

Cloudflare's global network can deliver content to website visitors using Gzip compression, Brotli compression, Zstandard compression, or no compression, depending on:

* The values visitors provide in the `accept-encoding` request header.
* Your [Cloudflare plan](#between-visitors-and-cloudflare).
* Any configured [compression rule](https://developers.cloudflare.com/rules/compression-rules/) that matches incoming requests.

For responses with error status codes, Cloudflare will only compress responses if their error status code is `403` or `404`. For successful response status codes, Cloudflare will only compress responses if their status code is `200`. Responses with other status codes will not be compressed.

You can override Cloudflare's default compression behavior using [Compression Rules](https://developers.cloudflare.com/rules/compression-rules/).

Minimum response size for compression

Cloudflare will only apply compression to responses with a minimum size when sending them to website visitors:

* For Gzip, responses must have a minimum size of 48 bytes.
* For Brotli and Zstandard, responses must have a minimum size of 50 bytes.

Smaller responses will not be compressed, regardless of their content type.

### Content-Length header handling

When Cloudflare compresses a response sent to the website visitor, it may omit the `Content-Length` HTTP header to avoid delivering incorrect length information caused by dynamic transformations. To preserve the `Content-Length` header set by the origin server, add `cache-control: no-transform` to the origin server's response. This directive prevents Cloudflare from altering compression on responses, allowing the `Content-Length` header to pass through as-is. The `cache-control: no-transform` header must be set by the origin — it cannot be added in client requests.

---

## Content compression from origin servers to the Cloudflare network

When requesting content from your origin server, Cloudflare supports Brotli compression, Gzip compression, or no compression.

flowchart LR
accTitle: Compressed responses sent from the origin server
accDescr: Cloudflare accepts responses from origin server using Brotli compression, Gzip compression, or no compression.

A[Visitor browser]
B((Cloudflare))
C[(Origin server)]

A -.-> B == "Request<br>Accept-Encoding: br, gzip" ==> C
C == "Response<br>(Brotli / Gzip / No compression)" ==> B -.-> A

style A stroke-dasharray: 5 5
style B stroke: orange,fill: orange,color: black
style C stroke-width: 2px
linkStyle 1,2 stroke-width: 2px
linkStyle 0,3 stroke-width: 1px

If your origin server responds to a Cloudflare request using Brotli/Gzip compression, we will keep the same compression in the response sent to the website visitor if:

* You include a `content-encoding` header in your server response mentioning the compression being used (`br` or `gzip`).
* The visitor browser (or client) supports the compression algorithm.
* You do not enable Cloudflare features that change the response content (refer to [Notes about end-to-end compression](#notes-about-end-to-end-compression) for details).

Cloudflare's reverse proxy can also convert between compressed formats and uncompressed formats. Cloudflare can receive content from your origin server with Brotli or Gzip compression and serve it to visitors uncompressed (or vice versa), independently of caching.

If you do not want a particular response from your origin to be encoded with Brotli/Gzip when delivered to website visitors, you can disable this by including a `cache-control: no-transform` HTTP header in the response from your origin web server.

Warning

Cloudflare will take into consideration the `accept-encoding` header value in website visitors' requests when sending responses to those visitors. However, when requesting content from your origin server, Cloudflare will send a different `Accept-Encoding` header, supporting Brotli and Gzip compression.

---

## Notes about end-to-end compression

### Content recompression due to dynamic transformations

Even when using the same compression algorithm end to end (between your origin server and Cloudflare, and between the Cloudflare global network and your website visitor), Cloudflare will need to decompress the response and compress it again if you enable any of the following settings for the request:

* [Automatic HTTPS Rewrites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/automatic-https-rewrites/)
* [Cloudflare Fonts](https://developers.cloudflare.com/speed/optimization/content/fonts/)
* [Email Address Obfuscation](https://developers.cloudflare.com/waf/tools/scrape-shield/email-address-obfuscation/)
* [Polish](https://developers.cloudflare.com/images/polish/)
* [Rocket Loader](https://developers.cloudflare.com/speed/optimization/content/rocket-loader/)
* [JavaScript detections](https://developers.cloudflare.com/bots/additional-configurations/javascript-detections/)
* [RUM](https://developers.cloudflare.com/speed/observatory/run-speed-test/#enable-real-user-monitoring-rum)

To disable these settings for specific URI paths, create a [configuration rule](https://developers.cloudflare.com/rules/configuration-rules/).

Note

Additionally, the [Replace insecure JS libraries](https://developers.cloudflare.com/waf/tools/replace-insecure-js-libraries/) setting also requires Cloudflare to decompress the response and compress it again. At this time, you cannot turn it off using Configuration Rules.

### Content-Length header

Cloudflare may remove the `Content-Length` HTTP header of responses delivered to website visitors. To ensure that the header is preserved, add a `cache-control: no-transform` HTTP header to the response at the origin server.

## Compression methods by plan

### Between visitors and Cloudflare

By default, Cloudflare uses the following compression methods for content delivery, depending on the zone plan. However, the actual compression applied may also depend on what the visitor's browser requests via the `accept-encoding` header.

* Free Plan: Content is compressed by default using Zstandard.
* Pro and Business Plans: Content is compressed by default using Brotli.
* Enterprise Plan: Content is compressed by default using Gzip.

### Between Cloudflare and the origin server

On all plans, Cloudflare requests content from the origin server using the `accept-encoding: br, gzip` header. This means that Cloudflare asks the origin to send the content compressed using Brotli or Gzip, depending on which method the origin server supports.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/content/","name":"Content optimizations"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/content/compression/","name":"Content compression"}}]}
```

---

---
title: Early Hints
description: Preload assets with 103 Early Hints to speed up page loads.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Early Hints

When a browser requests a page, the origin server takes time to prepare the full response. Early Hints uses this wait time to send the browser a preliminary `103` response containing `Link` headers that tell the browser which assets it will need. The browser can start loading those assets before the full response arrives, which speeds up page loads.

Early Hints is defined in [RFC 8297 ↗](https://httpwg.org/specs/rfc8297.html) as a new HTTP status code (`103 Early Hints`). Cloudflare caches and serves these `103` responses with `Link` headers from your HTML pages, reducing user-perceived latency.

Note

Early Hints is currently only supported over HTTP/2 and HTTP/3.

For more information about Early Hints, refer to the [Cloudflare ↗](https://blog.cloudflare.com/early-hints) and [Google Chrome ↗](https://developer.chrome.com/en/blog/early-hints/) blogs.

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

## Enable Early Hints

1. In the Cloudflare dashboard, go to the **Speed** \> **Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/speed/optimization)
2. Go to the **Content Optimization** tab.
3. For **Early Hints**, toggle the switch to **On**.

## Generate Early Hints

Early Hints are only generated and cached:

* For URIs with `.html`, `.htm`, or `.php` file extensions, or no file extension
* On 200, 301, or 302 response return codes
* When the response contains [link headers ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Link) with preconnect or preload rel types, such as `Link: </img/preloaded.png>; rel=preload`

Note

Early Hints cache entries are keyed by request URI and ignore query strings.

## Emit Early Hints

Cloudflare will asynchronously look up and emit a cached 103 Early Hints response ahead of a main response.

Currently, only certain browser versions will take action to preload or preconnect on receiving Early Hints, such as Google Chrome M94 and higher. Instructions for running WebPageTest to experiment with compatible client browsers can be found in the [blog post ↗](https://blog.cloudflare.com/early-hints/#testing-early-hints-with-web-page-test).

Additionally, keep the following in mind:

* Early Hints responses may be emitted before reaching the origin server or Worker. When Early Hints is enabled and pages on your site require authentication, unauthenticated visitors may receive a 103 response. The 103 response would contain cached Link headers and be sent before a 403 Forbidden response from your origin.
* Early Hints may be emitted less frequently on requests where the content is cacheable. Cloudflare CDN is more likely to retrieve a response header before the asynchronous Early Hints lookup finishes if the response has been cached. Cloudflare will not send a 103 response if the main response header is already available.
* Cloudflare currently disables Early Hints on some User-Agents, for example, select search crawler bots that show incompatibility with 1xx responses.
* You may see an influx of `504` responses with the `RequestSource` of `earlyHintsCache` in Cloudflare Logs when Early Hints is enabled, which is expected and benign. Requests from `earlyHintsCache` are internal subrequests for cached Early Hints, and they are neither end user requests, nor do they go to your origin. Their response status only indicates whether there are cached Early Hints for the request URI (`200` on cache HIT, `504` on cache MISS). These requests are already filtered out in other views, such as Cache Analytics. To filter out these requests or to filter requests by end users of your website only, please refer to [Filter end users](https://developers.cloudflare.com/analytics/graphql-api/features/filtering/#filter-end-users).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cache/","name":"Cache / CDN"}},{"@type":"ListItem","position":3,"item":{"@id":"/cache/advanced-configuration/","name":"Advanced configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/cache/advanced-configuration/early-hints/","name":"Early Hints"}}]}
```

---

---
title: Cloudflare Fonts
description: Serve Google Fonts from your domain to improve privacy and performance.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare Fonts

Cloudflare Fonts is a feature designed for websites that use [Google Fonts ↗](https://fonts.google.com/). It rewrites Google Fonts to be delivered from a website’s own origin, eliminating the need to rely on third-party font providers. Cloudflare Fonts is tailored to improve website performance and user privacy without the need for any code changes or self-hosting of fonts.

## How Cloudflare Fonts works

Cloudflare Fonts works by rewriting your webpage’s HTML. It removes Google Fonts links and replaces them with inline CSS. This CSS includes links to fonts from your own Cloudflare zone rather than from Google servers. This ensures that font files are served from your domain through Cloudflare's infrastructure, optimizing performance and enhancing user privacy.

### Browser support

Cloudflare Fonts is compatible with browsers that support Unicode-range subsetting and WOFF or WOFF2 formats, including:

```

Chrome 36+

Edge 16+

Safari 10+

Firefox 44+

Opera 22+

IE 9+

Chrome for Android 115+

Safari on iOS 10+

Samsung Internet 5+


```

## Get started

To enable Cloudflare Fonts for your entire domain:

1. In the Cloudflare dashboard, go to the **Speed** \> **Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/speed/optimization)
2. Go to **Content Optimization**.
3. For **Cloudflare Fonts**, switch the toggle to **On**.

Note

To use this feature on specific hostnames - instead of across your entire zone - use a [configuration rule](https://developers.cloudflare.com/rules/configuration-rules/).

## Limitations

While Cloudflare Fonts offers powerful font optimization capabilities, it is important to be aware of its limitations:

* **Font transformation**: Currently, Cloudflare Fonts exclusively supports Google Fonts transformation.
* **APO compatibility**: Cloudflare Fonts does not operate when [Automatic Platform Optimization](https://developers.cloudflare.com/automatic-platform-optimization/) (APO) is enabled. Cloudflare APO automatically optimizes Google Fonts in a similar way.
* **CSS import**: Cloudflare Fonts is compatible only with the `<link>` setup for Google Fonts and does not support the CSS `@import` method.
* **CSP headers**: Cloudflare Fonts does not modify [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy) headers. Certain CSP configurations may make Cloudflare Fonts stop working, such as restrictions on inline styles through [style-src ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/style-src), or restriction of fonts originating from the site's own origin via [font-src ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/font-src).
* **Fallback mechanism**: In cases where Cloudflare Fonts does not support a specific page, it will gracefully fallback to using Google Fonts.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/content/","name":"Content optimizations"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/content/fonts/","name":"Cloudflare Fonts"}}]}
```

---

---
title: FAQ
description: Read FAQs about Cloudflare Fonts
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# FAQ

In the following sections, you can find frequently asked questions about performance, privacy, security, implementation and integration.

## Performance

### How does Cloudflare Fonts improve website performance?

By serving fonts from your own domain through Cloudflare's optimized infrastructure, Cloudflare Fonts reduces DNS lookups, TLS connection setups and latency. This leads to faster page load times, enhancing the overall performance of your website.

## Privacy and security

### Does Cloudflare Fonts collect or log user data?

No, Cloudflare Fonts does not collect or log user data during the font delivery process. Cloudflare is committed to a [privacy-first ↗](https://www.cloudflare.com/privacypolicy/) approach, ensuring that your users' data remains confidential.

## Implementation and integration

### Do I need to host my font files separately when using Cloudflare Fonts?

No, Cloudflare Fonts simplifies the font delivery process. You do not need to host font files separately. The service works by rewriting the webpage’s HTML. It removes Google Fonts links and replaces them with inline CSS.

### Are there any code changes required to use Cloudflare Fonts?

No, you do not need any code changes to use Cloudflare Fonts.

### Can I see analytics of font files served via Cloudflare Fonts?

Yes, as Cloudflare will be serving these fonts via your zone, analytics will appear within your Cloudflare dashboard. This allows you to analyze requests for font files that you would not have otherwise known about without Cloudflare Fonts.

### Which path are Cloudflare Fonts requests made to?

Font requests will be made to your origin with the `/cf-fonts/` path prefix.

### What other transformations are made?

Cloudflare will strip any preconnect headers for Google Fonts domains from the HTML response body. This will improve performance by removing unnecessary connections.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/content/","name":"Content optimizations"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/content/fonts/","name":"Cloudflare Fonts"}},{"@type":"ListItem","position":6,"item":{"@id":"/speed/optimization/content/fonts/faq/","name":"FAQ"}}]}
```

---

---
title: Troubleshooting
description: Troubleshoot issues with Cloudflare Fonts
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

## Validate the Fonts feature is working

To test that the Fonts feature is working correctly, follow these steps:

1. With the Fonts feature disabled, navigate to your webpage and open the network panel in your browser's developer tools. For Chrome, right click on the webpage and select **Inspect**, which open the developer tools. Next, navigate to the **Network** tab within the console.
2. Reload the page.
3. In the Network tab, you should have a request to `fonts.googleapis.com`, and a request to `fonts.gstatic.com`. This means that Google Fonts are being downloaded for this page. If you do not have these requests in the list, either your webpage is not using Google Fonts, or your hosting provider might be optimizing the Google Fonts in some other way.
4. [Enable Cloudflare Fonts](https://developers.cloudflare.com/speed/optimization/content/fonts/#get-started) and wait for a few seconds.
5. In the inspect window, toggle **Disable cache** on and reload the page.
6. In the network panel, you should now have a request to your zone on the `/cf-fonts/` path prefix. The requests to `fonts.googleapis.com` and `fonts.gstatic.com` should have disappeared. This means the feature is working correctly.

## Feature is not working

For the feature to work, the response HTML (when the feature is disabled) must include a link tag with `href` pointing to `fonts.googleapis.com`. You can check this on the browser by viewing the source code of the webpage. As an example of what to look for, the following link tag is for the Roboto Google Font:

```

<link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">


```

If the tag does not exist in the HTML, but you are still sure that your page is using Google Fonts, it might be that your hosting provider is optimizing your Google Fonts on the server. This can prevent Cloudflare Fonts from working properly.

## Other issues with Cloudflare Fonts

If you experience any issues or have questions while using Cloudflare Fonts, refer to the [Cloudflare Community ↗](https://community.cloudflare.com/) pages or contact [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) for assistance.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/content/","name":"Content optimizations"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/content/fonts/","name":"Cloudflare Fonts"}},{"@type":"ListItem","position":6,"item":{"@id":"/speed/optimization/content/fonts/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: Prefetch URLs
description: Prefetch URLs to load resources before visitors request them.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Prefetch URLs

URL prefetching means that Cloudflare pre-populates the cache with content a visitor is likely to request next. This setting — when combined with [additional setup](#setup) — leads to a higher cache hit rate and thus a faster experience for the user.

---

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | No  | No       | No         | Yes |

---

## Setup

For Cloudflare to start prefetching URLs, you will need to [enable the feature](#enable-prefetch-urls) and [include a list of URLs to prefetch](#choose-urls-to-prefetch).

### Enable Prefetch URLs

* [ Dashboard ](#tab-panel-10391)
* [ API ](#tab-panel-10392)

To enable **Prefetch URLs** in the dashboard:

1. In the Cloudflare dashboard, go to the **Speed** \> **Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/speed/optimization)
2. Go to **Content Optimization**.
3. For **Prefetch URLs**, switch the toggle to **On**.

To enable or disable **Prefetch URLs** with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `prefetch_preload` as the setting name in the URI path, and the `value` parameter set to your desired setting (`"on"` or `"off"`).

### Choose URLs to prefetch

After you [enable the feature](#enable-prefetch-urls), you also need to indicate which URLs Cloudflare should prefetch.

To do this, include a Link HTTP response header pointing to a manifest file with the `rel="prefetch"` attribute and then serve the manifest file with `text/plain` as the Content-type response header.

Example HTTP response header:  
`Link: <http://www.example.com/manifest.txt>; rel="prefetch"`

Example `manifest.txt` file:

```

/static/fetch1

//other.example.com/fetch2

http://another.example.com/fetch3


```

The manifest file should contain URIs, protocol-relative URLs or full URLs, separated by new lines. These files must be on your websites that are on Cloudflare. If you reference HTML pages, only the HTML page itself will be pre-fetched - any sub-requests from that HTML will not be fetched unless they are also defined explicitly in your manifest.

Note

The IP address used to make the prefetch request to the manifest file is logged as `127.0.0.1` in your Cloudflare logs.

### Prefetch files limits

The prefetch files limits are the following:

* The maximum number of manifest files is 16.
* The maximum number of files per manifest file is 100.
* A manifest file has a size limit of 1 MB.

## Limitations

* Cloudflare will only prefetch files listed in the manifest file if the resources are those [cached by default](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#default-cached-file-extensions).
* Prefetch is not compatible with the custom cache key configuration. For more information, refer to [Cache Key limitations](https://developers.cloudflare.com/cache/how-to/cache-keys/#limitations).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/content/","name":"Content optimizations"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/content/prefetch-urls/","name":"Prefetch URLs"}}]}
```

---

---
title: Rocket Loader
description: Defer JavaScript loading to improve page rendering speed.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Rocket Loader

Rocket Loader prioritizes your website's content (text, images, fonts, and more) by deferring the loading of all of your JavaScript until after rendering.

This type of loading (known as asynchronous loading) leads to earlier rendering of your page content. Rocket Loader handles both inline and external scripts, while maintaining order of execution. Cloudflare will detect incompatible browsers and disable Rocket Loader.

On pages with JavaScript, this results in a [much faster loading experience ↗](https://www.cloudflare.com/learning/performance/test-the-speed-of-a-website/) for your users and improves the following performance metrics:

* Time to First Paint (TTFP)
* Time to First Contentful Paint (TTFCP)
* Time to First Meaningful Paint (TTFMP)
* Document Load

## How to

* [ Enable ](https://developers.cloudflare.com/speed/optimization/content/rocket-loader/enable/)
* [ Ignore JavaScripts ](https://developers.cloudflare.com/speed/optimization/content/rocket-loader/ignore-javascripts/)

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

## Limitations

Some of Cloudflare's optional features, including Rocket Loader and Email Obfuscation, use non standard tags that fail strict HTML validation via tools like [w3.org ↗](https://validator.w3.org/). These failures do not correlate to issues for your site visitors.

If you observe JavaScript or jQuery issues for your website, [disable Rocket Loader](https://developers.cloudflare.com/speed/optimization/content/rocket-loader/enable/) and retest your website.

If you have a Content Security Policy (CSP) in place for your domain, you will need to [update your headers](https://developers.cloudflare.com/fundamentals/reference/policies-compliances/content-security-policies/#product-requirements) to support Rocket Loader.

  

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/content/","name":"Content optimizations"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/content/rocket-loader/","name":"Rocket Loader"}}]}
```

---

---
title: Enable
description: Turn on Rocket Loader for your zone.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Enable

To enable or disable Rocket Loader, use the following instructions.

* [ Dashboard ](#tab-panel-10393)
* [ API ](#tab-panel-10394)

To enable or disable **Rocket Loader** in the dashboard:

1. In the Cloudflare dashboard, go to the **Speed** \> **Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/speed/optimization)
2. Go to **Content Optimization**.
3. For **Rocket Loader**, switch the toggle to **On**.

If you have a Content Security Policy (CSP) in place for your domain, you will need to [update your headers](https://developers.cloudflare.com/fundamentals/reference/policies-compliances/content-security-policies/#product-requirements) to support Rocket Loader.

To enable or disable **Rocket Loader** with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `rocket_loader` as the setting name in the URI path, and the `value` parameter set to `"on"` or `"off"`.

If you have a Content Security Policy (CSP) in place for your domain, you will need to [update your headers](https://developers.cloudflare.com/fundamentals/reference/policies-compliances/content-security-policies/#product-requirements) to support Rocket Loader.

Note

To use this feature on specific hostnames - instead of across your entire zone - use a [configuration rule](https://developers.cloudflare.com/rules/configuration-rules/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/content/","name":"Content optimizations"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/content/rocket-loader/","name":"Rocket Loader"}},{"@type":"ListItem","position":6,"item":{"@id":"/speed/optimization/content/rocket-loader/enable/","name":"Enable"}}]}
```

---

---
title: Ignore JavaScripts
description: Exclude specific scripts from Rocket Loader optimization.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Ignore JavaScripts

You can have Rocket Loader ignore individual scripts by adding the `data-cfasync="false"` attribute to the relevant script tag:

```

<script data-cfasync="false" src="/javascript.js"></script>


```

Rocket Loader will still optimize the loading of all other scripts on the page.

Note

If Rocket Loader is only impacting a specific page, use a [Configuration Rule](https://developers.cloudflare.com/rules/configuration-rules/) to exclude that page by URL.

## Limitations

* Adding this attribute within JavaScript will not work if you wish to exclude the script from Rocket Loader.
* If the script you want Rocket Loader to ignore has dependency on other JavaScript(s) on the page, those dependencies must also have the `data-cfasync="false"` attribute.
* The `data-cfasync` attribute must be added before the `src` attribute.
* Rocket Loader will recognize the tag when either single or double quotes are placed around the attribute value.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/content/","name":"Content optimizations"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/content/rocket-loader/","name":"Rocket Loader"}},{"@type":"ListItem","position":6,"item":{"@id":"/speed/optimization/content/rocket-loader/ignore-javascripts/","name":"Ignore JavaScripts"}}]}
```

---

---
title: Shared dictionaries
description: Shared dictionaries reduce repeat-visitor transfer size by compressing each response against a version the browser already has cached.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Shared dictionaries

Shared dictionaries ([RFC 9842 ↗](https://datatracker.ietf.org/doc/rfc9842/)) let your origin compress a response against a copy of the same — or a different — resource that the visitor's browser already has cached. Only the difference between the two resources travels over the wire.

This is most effective for versioned assets that change incrementally between deploys, such as JavaScript bundles, CSS files, and framework chunks. After a deploy, returning visitors can receive the new asset as a small delta against the version they already have, instead of redownloading the full file.

Cloudflare supports shared dictionaries in **passthrough** mode: your origin manages dictionaries and produces delta-compressed responses. Cloudflare forwards the dictionary headers and `dcb`/`dcz` content encodings without modifying or recompressing them, and varies the cache so each delta-compressed variant is stored separately.

For background on the other compression algorithms Cloudflare supports, refer to [Content compression](https://developers.cloudflare.com/speed/optimization/content/compression/).

---

## Availability

| Free         | Pro        | Business   | Enterprise |            |
| ------------ | ---------- | ---------- | ---------- | ---------- |
| Availability | Yes (beta) | Yes (beta) | Yes (beta) | Yes (beta) |

---

## Requirements

Shared dictionaries work when all of the following are true:

* The visitor's browser supports [compression dictionary transport ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Compression%5Fdictionary%5Ftransport). Today, this is Chrome 130 or later, Edge 130 or later, or another Chromium browser at the same version.
* The browser request includes `dcb` or `dcz` in `Accept-Encoding` and an `Available-Dictionary` header.
* Your origin returns a delta-compressed response with `Content-Encoding: dcb` or `dcz` and a `Vary` header that includes `Accept-Encoding, Available-Dictionary`.
* The dictionary, the delta response, and the request are served over HTTPS from the same origin. Per [RFC 9842, Section 8 ↗](https://www.rfc-editor.org/rfc/rfc9842.html#section-8), compression dictionary transport is HTTPS-only.

---

## How shared dictionaries work

The protocol uses two new request and response headers and two new content encodings:

| Header                       | Direction        | Purpose                                                                                           |
| ---------------------------- | ---------------- | ------------------------------------------------------------------------------------------------- |
| Use-As-Dictionary            | Origin → browser | Marks a response as usable as a dictionary for future requests matching the supplied match value. |
| Available-Dictionary         | Browser → origin | Advertises the SHA-256 hash of a dictionary the browser already has for the request URL.          |
| Content-Encoding: dcb or dcz | Origin → browser | Delta-compressed against the advertised dictionary, using Brotli (dcb) or Zstandard (dcz).        |

The first response for a versioned asset includes `Use-As-Dictionary`, and the browser stores the response. On subsequent requests for assets matching the pattern, the browser sends `Available-Dictionary: :<sha256>:` and adds `dcb, dcz` to `Accept-Encoding`. Your origin compresses the new asset against the dictionary and returns it with `Content-Encoding: dcb` or `dcz`. The browser uses its stored copy to reconstruct the full response.

The `match` value in `Use-As-Dictionary` is a [WHATWG URL Pattern ↗](https://urlpattern.spec.whatwg.org/), not a regular expression. Match patterns operate on the percent-encoded URL path and are scoped to the same origin as the dictionary.

The `Available-Dictionary` value is a [Structured Field ↗](https://www.rfc-editor.org/rfc/rfc9651) byte sequence: the base64-encoded SHA-256 hash wrapped in colons (for example, `:pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4=:`). The colons are part of the syntax.

---

## Enable shared dictionaries

Enabling shared dictionaries is a two-part task:

1. Turn on passthrough for your zone in Cloudflare. This tells Cloudflare to forward dictionary headers and vary cache entries correctly.
2. Update your origin server to mark assets as dictionaries and return delta-compressed responses against them.

The work of creating dictionaries and compressing new responses against them happens at your origin, not at Cloudflare.

### 1\. Enable passthrough in Cloudflare

* [ Dashboard ](#tab-panel-10395)
* [ API ](#tab-panel-10396)
* [ Terraform ](#tab-panel-10397)

To enable shared dictionaries in the dashboard:

1. In the Cloudflare dashboard, go to the Speed **Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/speed/optimization)
2. Go to **Content Optimization**.
3. Toggle **Shared Dictionaries** to **On**.

Use the following `PATCH` request to enable shared dictionaries:

Terminal window

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/shared_dictionary_mode" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": "passthrough"

  }'


```

To turn shared dictionaries off, set `value` to `"disabled"`.

Valid values for this setting are:

| Value       | Behavior                                                                                                                                 |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| passthrough | Cloudflare forwards shared dictionary request and response headers, accepts dcb/dcz responses from the origin, and varies cache entries. |
| disabled    | Cloudflare strips shared dictionary headers and does not cache dcb/dcz variants.                                                         |

You can configure shared dictionaries using the `cloudflare_zone_settings_override` resource. For more details, refer to the [Terraform documentation ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs).

Note

Because `shared_dictionary_mode` is a zone setting, it is not compatible with [Cloudflare Version Management](https://developers.cloudflare.com/version-management/). You can enable passthrough in a non-production version, validate that origin responses are correct end to end, and promote to production with a single deploy on a new zone.

### 2\. Mark assets as dictionaries at your origin

For each versioned asset you want to use as a dictionary, include a `Use-As-Dictionary` header on the first response:

```

Use-As-Dictionary: match="/static/app-*.js", type="raw"

Cache-Control: public, max-age=31536000, immutable

Content-Encoding: br


```

The `match` value tells the browser which future request URLs should advertise this dictionary. It is a WHATWG URL Pattern, does not support regular expressions, and must resolve to the same origin as the dictionary.

### 3\. Compress new versions against the advertised dictionary

When a request arrives with an `Available-Dictionary` header, look up the dictionary by its SHA-256 hash. If you have it, compress the response against it and return:

```

Content-Encoding: dcz

Vary: Accept-Encoding, Available-Dictionary

Cache-Control: public, max-age=31536000, immutable


```

[RFC 9842, Section 6.2 ↗](https://www.rfc-editor.org/rfc/rfc9842.html#section-6.2) requires the `Vary: Accept-Encoding, Available-Dictionary` response header so that browser caches do not serve the wrong variant. Cloudflare's cache also varies on these headers when passthrough is on.

### 4\. Fall back when no dictionary is available

When the browser does not advertise `Available-Dictionary`, the hash does not match a dictionary you have, or the browser does not advertise `dcb`/`dcz`, return the response with normal Brotli, Zstandard, or Gzip compression.

### Implementation options

Cloudflare does not prescribe a specific origin implementation. Common starting points include:

* **A reverse proxy.** Configure NGINX, Caddy, or a similar proxy to attach `Use-As-Dictionary` headers and produce delta responses with a sidecar process.
* **Native support in your application server.** Extend your existing compression middleware to read `Available-Dictionary` and emit `dcb` or `dcz`.

---

## Test shared dictionaries

To confirm a request is using a shared dictionary, request the asset twice. The second request advertises the dictionary you received in the first response.

Terminal window

```

# Prime the dictionary.

curl -sI -H "Accept-Encoding: br, gzip, zstd, dcb, dcz" \

  https://example.com/static/app.v1.js


# Request the next version, advertising the dictionary you just received.

# Replace <hash> with the base64-encoded SHA-256 of the first response.

# The surrounding colons are part of the Structured Field syntax

# and are required by RFC 9842, Section 2.2.

curl -sI -H "Accept-Encoding: br, gzip, zstd, dcb, dcz" \

  -H "Available-Dictionary: :<hash>:" \

  https://example.com/static/app.v2.js


```

The second response should include `Content-Encoding: dcz` (or `dcb`), `Vary: Accept-Encoding, Available-Dictionary`, and a `Content-Length` significantly smaller than a non-delta response.

You can also use [canicompress.com ↗](https://canicompress.com/) to confirm your browser supports shared dictionaries and to inspect a working delta-compressed response.

---

## Limitations

* **Origin-side work is required.** In passthrough mode, Cloudflare does not generate dictionaries or compute deltas. If your origin does not produce `dcb`/`dcz` responses, no compression savings occur.
* **Body-modifying features are incompatible.** Cloudflare features that rewrite response bodies do not work on delta-compressed responses. Turn these features off on dictionary-compressed paths, or set `cache-control: no-transform` on the origin response. For details, refer to [Content compression](https://developers.cloudflare.com/speed/optimization/content/compression/).
* **Browser support is partial.** Visitors on browsers that do not request `dcb` or `dcz` continue to receive Brotli, Zstandard, or Gzip per your existing [Compression Rules](https://developers.cloudflare.com/rules/compression-rules/) and [default compression behavior](https://developers.cloudflare.com/speed/optimization/content/compression/).
* **Same-origin only.** Per [RFC 9842, Section 9.3.1 ↗](https://www.rfc-editor.org/rfc/rfc9842.html#section-9.3.1), dictionaries are scoped to the response origin. Cross-origin dictionary use is not supported.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/content/","name":"Content optimizations"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/content/shared-dictionaries/","name":"Shared dictionaries"}}]}
```

---

---
title: Speed Brain
description: Learn how Speed Brain enhances web performance by prefetching likely next pages, improving metrics like LCP and TTFB.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Speed Brain

Speed Brain is a tool for improving web page performance by prefetching the most likely next navigation.

---

## Availability

| Free         | Pro                | Business | Enterprise |     |
| ------------ | ------------------ | -------- | ---------- | --- |
| Availability | Enabled by default | Yes      | Yes        | Yes |

---

## Requirements

Speed Brain works under the following conditions:

* The Speed Brain feature is enabled in Cloudflare.
* The browser of the web page visitor is using a Chromium-based browser version 121 or later.
* The web page requested by the prefetch is eligible for cache.
* The page requested by the prefetch does not invoke a Worker.

## What is Speed Brain?

The overall goal of Speed Brain is to try to download a webpage to the browser before a user navigates to it.

Cloudflare leverages the [Speculation Rules API ↗](https://developer.mozilla.org/en-US/docs/Web/API/Speculation%5FRules%5FAPI) to improve web page performance by instructing the browser to consider prefetching future navigations. Speed Brain does not improve page load time for the first page that is visited on a website, but it can improve it for subsequent web pages that are navigated to on the same site.

By prefetching pages that the browser considers likely to be navigated to, Speed Brain can enhance key metrics like [Largest Content Paint ↗](https://web.dev/articles/lcp) (LCP), [Time to First Byte ↗](https://web.dev/articles/ttfb) (TTFB) and overall page load time.

## How Speed Brain works

When Cloudflare's Speed Brain feature is enabled, an HTTP header called `Speculation-Rules` is added to web page responses. The value for this header is a URL that hosts an opinionated Speculation-Rules configuration. This configuration instructs the browser to consider prefetching any future navigations with a `conservative` [eagerness ↗](https://developer.chrome.com/docs/web-platform/prerender-pages#eagerness).

The configuration looks like this:

```

{

  "prefetch": [

    {

      "source": "document",

      "where": {

        "and": [{ "href_matches": "/*", "relative_to": "document" }]

      },

      "eagerness": "conservative"

    }

  ]

}


```

This configuration instructs the browser to initiate prefetch requests for future navigations. These prefetch requests will include the `sec-purpose: prefetch` HTTP request header. Prefetches that are not successful will respond with a `503` status code. Prefetches that are successful will respond with a `200` status code.

## Test Speed Brain

To test that Speed Brain is enabled, you can check that your HTTP response headers for your web pages include the `Speculation-Rules` header. However, note that during the beta phase of Speed Brain, this behavior might not be 100% consistent.

To test whether your browser is making prefetch requests, open the **Network** tab in Chrome DevTools. Then, mouse-down on a link on a webpage with Speed Brain enabled. This action should initiate a prefetch request, which will be visible in the **Network** tab. However, note that there are several reasons why the browser might choose not to initiate a prefetch. Refer to the [Chrome Limits guide ↗](https://developer.chrome.com/docs/web-platform/prerender-pages#chrome-limits) for more details. For more general information about debugging Speculation-Rules, refer to the [Chrome Speculation Debugging guide ↗](https://developer.chrome.com/docs/devtools/application/debugging-speculation-rules).

## RUM integration

Speed Brain is designed to integrate with Web Analytics & Real User Measurements (RUM). This integration allows you to understand the web performance implications of Speed Brain within the Web Analytics interface in Cloudflare's Dashboard.

While you can use Speed Brain without RUM enabled, you will not have visibility into how the feature is affecting the performance of your web pages. For further details on how to set up RUM, refer to the [Web Analytics & RUM](https://developers.cloudflare.com/web-analytics/) documentation.

## Enable and disable Speed Brain

Speed Brain is available in Cloudflare's **Speed** tab of the dashboard and also in the API.

* [ Dashboard ](#tab-panel-10398)
* [ API ](#tab-panel-10399)
* [ Terraform ](#tab-panel-10400)

To enable or disable **Speed Brain** in the dashboard:

1. In the Cloudflare dashboard, go to the **Speed** \> **Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/speed/optimization)
2. Go to **Content Optimization**.
3. Toggle **Speed Brain** to **On** or **Off**.

Use the following `PATCH` request to enable Speed Brain:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`

Change Cloudflare Speed Brain setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/speed_brain" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": "on"

  }'


```

To disable Speed Brain, set `value:` to `"off"`.

You can also configure Speed Brain using Terraform. For more details, refer to the `cloudflare_zone_settings_override` resource in the [Terraform documentation ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs).

## Caveats

* Since prefetch responses are not guaranteed to be rendered by the browser, Speed Brain includes two safeguards to minimize the risk of [unsafe prefetching ↗](https://developer.mozilla.org/en-US/docs/Web/API/Speculation%5FRules%5FAPI#unsafe%5Fprefetching):  
   * Speed Brain will not prefetch on routes that run Workers. Without this safeguard, prefetch requests could inadvertently run Worker logic that assumes the incoming request is a normal (that is, not a prefetch) request. An example of this could be an incrementing page view counter running in a Worker. A page view counter should not increment if the page is not actually rendered in the browser.  
   * Prefetch requests will never reach origin servers. Prefetch requests only serve content that is stored in Cloudflare’s Cache. If the content is not in Cache, the prefetch request will not continue to origin servers. Without this safeguard, origin server state could be modified despite the prefetch response not being rendered in the browser. An example of this could be a prefetch `GET` request to a sign-out URL inadvertently triggering a sign-out action on the server.
* If origin server responses include the `Speculation-Rules` header, it will not be overridden.
* Speed Brain will not work with restrictive [Content Security Policy ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/script-src) configurations using `strict-dynamic` or `nonce-{hash}` attributes.
* Currently, Speed Brain is not compatible with websites that use or rely on `pages.dev`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/content/","name":"Content optimizations"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/content/speed-brain/","name":"Speed Brain"}}]}
```

---

---
title: Content encoding issues
description: Fix content encoding mismatches with compression settings.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Content encoding issues

If you are noticing any encoding errors with your HTML pages, we recommend verifying that the impacted pages are explicitly setting the correct charset in the `Content-Type` header from your origin for all text/html pages, for example `Content-Type: text/html; charset=utf-8`. This is particularly important if you are not using [UTF-8 encoding standard ↗](https://en.wikipedia.org/wiki/UTF-8) for characters. Alternatively you can set the correct charset within the HTML.

If you believe these settings are correct, please inform us. You can find more information in [setting the HTTP charset parameter ↗](https://www.w3.org/International/articles/http-charset/index) and in [HTML charset attribute ↗](https://www.w3schools.com/tags/att%5Fmeta%5Fcharset.asp).

Alternatively, you can use a [Configuration Rule](https://developers.cloudflare.com/rules/configuration-rules/) to disable features that rewrite HTML. This will send the content as-is to the browser.

You also have the option to turn off these features site-wide within the dashboard:

* [Email Obfuscation](https://developers.cloudflare.com/waf/tools/scrape-shield/email-address-obfuscation/), located in the **Security** \> **Settings** section.
* [Rocket Loader](https://developers.cloudflare.com/speed/optimization/content/rocket-loader/), located in **Speed** \> **Settings** \> **Content Optimization** section.
* [Automatic HTTPS Rewrites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/automatic-https-rewrites/), located in the **SSL/TLS** \> **Edge Certificates** section.

Misconfiguring the `Content-Type` or charset within HTML, or leaving them unspecified can lead to unintended consequences. This can disrupt the intended content presentation, resulting in disorganized rendering and potentially unclear characters. Properly configuring these elements ensures consistent and accurate interpretation, correct HTML modifications, and accurate rendering for browsers. This creates a seamless user experience and aligns with best practices in web development.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/content/","name":"Content optimizations"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/content/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":6,"item":{"@id":"/speed/optimization/content/troubleshooting/content-encoding-issues/","name":"Content encoding issues"}}]}
```

---

---
title: Turn off Auto Minify via API
description: Learn how to turn off Auto Minify via API in Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Turn off Auto Minify via API

If your site is still using deprecated features for [Auto Minify](https://developers.cloudflare.com/fundamentals/api/reference/deprecations/#2024-08-05), turn off Auto Minify via API.

## Before you begin

You will need an [API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) with the following permissions:

* _Zone_ \> _Zone Settings_ \> _Edit_
* _Zone_ \> _Zone Settings_ \> _Read_

## (Optional) Check zone status

To check your zone's Auto Minify status, send a `GET` request to the `/zones/{zone_id}/settings/minify` endpoint.

Terminal window

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/settings/minify" \

--header "Authorization: Bearer <API_TOKEN>"


```

```

{

  "result": {

    "id": "minify",

    "value": { "css": "off", "html": "off", "js": "off" },

    "modified_on": null,

    "editable": true

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

If any of the values in the highlighted line are `"on"`, then you need to turn them off.

## Turn off Auto Minify using the API

To turn off Auto Minify for your zone, send a `PATCH` request to the `/zones/{zone_id}/settings/minify` endpoint. The value for `success` in the response should be `true`.

Terminal window

```

curl --request PATCH \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/settings/minify" \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{ "value": { "css": "off","html": "off","js": "off" } }'


```

```

{

  "result": {

    "id": "minify",

    "value": { "js": "off", "css": "off", "html": "off" },

    "modified_on": "2024-11-15T19:32:20.882640Z",

    "editable": true

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/content/","name":"Content optimizations"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/content/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":6,"item":{"@id":"/speed/optimization/content/troubleshooting/disable-auto-minify/","name":"Turn off Auto Minify via API"}}]}
```

---

---
title: Overview
description: Cloudflare Images transformations optimize and cache remote images from any origin at the edge.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Overview

Transformations are requests to optimize and manipulate remote images that are stored outside of Images.

When you ship applications on Cloudflare, you can use Images to automatically optimize and cache your images from any origin.

Our image optimization pipeline provides a rich set of [features](https://developers.cloudflare.com/images/optimization/features) that can be applied across entire media libraries to compress images at scale, transcode files into efficient formats for delivery, and resize and crop images for different use cases and devices.

## How it works

You can request transformations by using a specially-formatted URL to serve images on your Cloudflare zone or through Workers.

To serve transformations on your zone, you must first enable the feature:

1. In the [Cloudflare dashboard ↗](https://dash.cloudflare.com/?to=/:account/images/transformations), go to **Images** \> **Transformations**.
2. Select the zone where you want to serve transformations.
3. Enable **transformations** on your zone.

When the browser requests a transformed image, Cloudflare checks the edge cache for a previously optimized version with the same parameters:

**On a cache hit** — Cloudflare serves the optimized image directly from the edge without contacting the origin or re-applying the optimization parameters.

**On a cache miss** — Cloudflare fetches the original image from the source origin, applies the requested parameters (e.g. `format`, `width`, `quality`), caches the transformed result, and serves it to the browser. The original image is also cached to speed up future transformations of the same source.

Each unique combination of source image and parameters is cached and billed separately. The first request for each unique version within a calendar month is billed as one [unique transformation](https://developers.cloudflare.com/images/optimization/features), regardless of cache status. Subsequent requests for this transformation do not incur billable usage within the same calendar month.

## Configure your zone

After enabling transformations on your zone, you can configure how Cloudflare handles transformation requests:

* **[Define source origins](https://developers.cloudflare.com/images/optimization/transformations/sources)** — Specify which origins Cloudflare can pull source images from. By default, Cloudflare only accepts source images from the same zone where transformations are served.
* **[Create transformation flows](https://developers.cloudflare.com/images/optimization/transformations/flows)** — Set up automated rules that apply image optimization to matching requests without requiring URL changes or custom code.
* **[Control origin access](https://developers.cloudflare.com/images/optimization/transformations/control-origin-access)** — Use Workers to add custom logic for validating and controlling access to source images.
* **[Set up rewrite rules](https://developers.cloudflare.com/images/optimization/transformations/rewrite-rules)** — Use Transform Rules to rewrite image URLs and serve transformations from custom paths.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/images/","name":"Cloudflare Images"}},{"@type":"ListItem","position":3,"item":{"@id":"/images/optimization/","name":"Optimization"}},{"@type":"ListItem","position":4,"item":{"@id":"/images/optimization/transformations/","name":"Remote images (transformations)"}},{"@type":"ListItem","position":5,"item":{"@id":"/images/optimization/transformations/overview/","name":"Overview"}}]}
```

---

---
title: Cloudflare Mirage (deprecated)
description: Lazy-load images and reduce bandwidth on mobile connections.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare Mirage (deprecated)

Deprecation notice

Mirage was deprecated on September 15, 2025 and is no longer available.

As an alternative, Cloudflare recommends using [lazy loading](https://developers.cloudflare.com/images/tutorials/optimize-mobile-viewing/) and [responsive images](https://developers.cloudflare.com/images/optimization/make-responsive-images/) to optimize image performance for all devices.

## What was Mirage?

Cloudflare Mirage was a mobile image optimization feature that reduced bandwidth usage and accelerated image loading on slow mobile connections and HTTP/1.

Mirage worked by:

* Replacing images with low-resolution thumbnails bundled together into one file.
* Acting as a lazy loader, deferring loading of higher-resolution images until they become visible.

## Why was it deprecated?

Modern web standards and browser capabilities have evolved to provide native support for many of Mirage's features:

* Native lazy loading with the `loading="lazy"` HTML attribute.
* Responsive images using `srcset` and `<picture>` elements.
* HTTP/2 and HTTP/3 providing better performance.
* Improved mobile networks reducing the need for aggressive optimization.

## Migration path

Instead of Mirage, use:

* **[Polish](https://developers.cloudflare.com/images/polish/)** \- Seamlessly optimizes images for all browsers, not only mobile, and keeps images at full resolution.
* **[Image Resizing](https://developers.cloudflare.com/images/optimization/transformations/overview/)** \- Combined with `loading="lazy"` and `srcset` HTML attributes, provides modern responsive image delivery.
* **[Lazy loading guide](https://developers.cloudflare.com/images/tutorials/optimize-mobile-viewing/)** \- Learn how to implement native lazy loading.
* **[Responsive images guide](https://developers.cloudflare.com/images/optimization/make-responsive-images/)** \- Create images that adapt to different devices.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/images/","name":"Image optimization"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/images/mirage/","name":"Cloudflare Mirage (deprecated)"}}]}
```

---

---
title: Cloudflare Polish
description: Cloudflare Polish automatically optimizes images by stripping metadata and applying lossy or lossless compression.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare Polish

Cloudflare Polish is a one-click image optimization product that automatically optimizes images in your site. Polish strips metadata from images and reduces image size through lossy or lossless compression to accelerate the speed of image downloads.

When an image is fetched from your origin, our systems automatically optimize it in Cloudflare's cache. Subsequent requests for the same image will get the smaller, faster, optimized version of the image, improving the speed of your website.

![Example of Polish compression's quality.](https://developers.cloudflare.com/_astro/polish.DBlbPZoO_Zd4DDj.webp) 

## Comparison

* **Polish** automatically optimizes all images served from your origin server. It keeps the same image URLs, and does not require changing markup of your pages.
* **Cloudflare Images** API allows you to create new images with resizing, cropping, watermarks, and other processing applied. These images get their own new URLs, and you need to embed them on your pages to take advantage of this service. Images created this way are already optimized, and there is no need to apply Polish to them.

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | No  | Yes      | Yes        | Yes |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/images/","name":"Cloudflare Images"}},{"@type":"ListItem","position":3,"item":{"@id":"/images/polish/","name":"Cloudflare Polish"}}]}
```

---

---
title: Image optimization on optimized images
description: How multiple image optimizations interact with each other.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Image optimization on optimized images

Cloudflare's [image optimization features](https://developers.cloudflare.com/speed/optimization/images/) will likely not help much if you are already optimizing your images in some way (Smush.it, etc.).

Cloudflare recommends not activating other services on top of Cloudflare, because this setup can lead to unexpected outcomes and potential issues.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/images/","name":"Image optimization"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/images/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":6,"item":{"@id":"/speed/optimization/images/troubleshooting/multiple-optimizations/","name":"Image optimization on optimized images"}}]}
```

---

---
title: Cf-Polished statuses
description: Learn about Cf-Polished statuses in Cloudflare Images. Understand how to handle missing headers, optimize image formats, and troubleshoot common issues.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cf-Polished statuses

If a `Cf-Polished` header is not returned, try [using single-file cache purge](https://developers.cloudflare.com/cache/how-to/purge-cache) to purge the image. The `Cf-Polished` header may also be missing if the origin is sending non-image `Content-Type`, or non-cacheable `Cache-Control`.

* `input_too_large`: The input image is too large or complex to process, and needs a lower resolution. Cloudflare recommends using PNG or JPEG images that are less than 4,000 pixels in any dimension, and smaller than 20 MB.
* `not_compressed` or `not_needed`: The image was fully optimized at the origin server and no compression was applied.
* `webp_bigger`: Polish attempted to convert to WebP, but the WebP image was not better than the original format. Because the WebP version does not exist, the status is set on the JPEG/PNG version of the response. Refer to [the reasons why Polish chooses not to use WebP](https://developers.cloudflare.com/images/polish/no-webp/).
* `cannot_optimize` or `internal_error`: The input image is corrupted or incomplete at the origin server. Upload a new version of the image to the origin server.
* `format_not_supported`: The input image format is not supported (for example, BMP or TIFF) or the origin server is using additional optimization software that is not compatible with Polish. Try converting the input image to a web-compatible format (like PNG or JPEG) and/or disabling additional optimization software at the origin server.
* `vary_header_present`: The origin web server has sent a `Vary` header with a value other than `accept-encoding`. If the origin web server is attempting to support WebP, disable WebP at the origin web server and let Polish perform the WebP conversion. Polish will still work if `accept-encoding` is the only header listed within the `Vary` header. Polish skips image URLs processed by [Cloudflare Images](https://developers.cloudflare.com/images/optimization/transformations/overview).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/images/","name":"Cloudflare Images"}},{"@type":"ListItem","position":3,"item":{"@id":"/images/polish/","name":"Cloudflare Polish"}},{"@type":"ListItem","position":4,"item":{"@id":"/images/polish/cf-polished-statuses/","name":"Cf-Polished statuses"}}]}
```

---

---
title: Troubleshoot missing images
description: Fix missing or broken images after enabling image optimization.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshoot missing images

If images are missing from your website, other Cloudflare features may be interfering with those images.

To troubleshoot:

1. Perform one of the following actions:  
   * [Purge cache](https://developers.cloudflare.com/cache/how-to/purge-cache) for the URL of the missing image file.  
   * [Temporarily pause Cloudflare](https://developers.cloudflare.com/fundamentals/manage-domains/pause-cloudflare/).  
   * Disable [Rocket Loader](https://developers.cloudflare.com/speed/optimization/content/rocket-loader/enable/).
2. Retest the image load in a private browser tab.
3. If the issue is not fixed, try another of the actions suggested in Step 1.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/images/","name":"Image optimization"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/images/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":6,"item":{"@id":"/speed/optimization/images/troubleshooting/troubleshooting-missing-images/","name":"Troubleshoot missing images"}}]}
```

---

---
title: Measurement
description: Measure the impact of speed optimizations on your site.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Measurement

Enable measurement to track your traffic in a privacy-first manner, optimizing your site's speed tools. To access this feature, you need to enable [Web Analytics](https://developers.cloudflare.com/web-analytics/) on your website. This analytics tool leverages [Real User Measurement](https://developers.cloudflare.com/speed/observatory/run-speed-test/#enable-real-user-monitoring-rum) (RUM) data, providing insights based on actual user interactions to enhance site performance effectively.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/measurement/","name":"Measurement"}}]}
```

---

---
title: 0-RTT Connection Resumption
description: Resume TLS connections faster with zero round-trip time.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 0-RTT Connection Resumption

Zero round trip time resumption (0-RTT) improves performance for clients who have previously connected to your website, reducing latency for returning users. This feature is especially beneficial for those who frequently visit your application or connect over mobile networks.

We support 0-RTT for GET, HEAD, and OPTIONS requests, facilitating faster responses for these types of requests. Note that 0-RTT is not supported for POST requests.

In line with 0-RTT standards, we add the `Early-Data: 1` header to 0-RTT requests, which allows origin servers to identify when a request has used 0-RTT resumption. Customers should be able to see the `Early-Data: 1` header for any 0-RTT requests connecting to their origin.

For more information on 0-RTT, including its functionality and potential limitations, refer to our [blog post ↗](https://blog.cloudflare.com/even-faster-connection-establishment-with-quic-0-rtt-resumption/).

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

## Enable 0-RTT Connection Resumption

By default, 0-RTT Connection Resumption is not enabled on your Cloudflare application.

* [ Dashboard ](#tab-panel-10401)
* [ API ](#tab-panel-10402)

To enable 0-RTT Connection Resumption in the dashboard:

1. In the Cloudflare dashboard, go to the **Speed** \> **Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/speed/optimization)
2. Go to the **Protocol Optimization** tab and under **0-RTT Connection Resumption**, switch the toggle to **On**.

To adjust your 0-RTT Connection Resumption settings with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `0rtt` as the setting name in the URI path, and the `value` parameter set to `"on"` or `"off"`.

Note

The 0-RTT Connection Resumption is only established between the client and Cloudflare. It does not extend to the origin server.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/protocol/","name":"Protocol optimization"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/protocol/0-rtt-connection-resumption/","name":"0-RTT Connection Resumption"}}]}
```

---

---
title: Enhanced HTTP/2 Prioritization
description: Improve page load order with Enhanced HTTP/2 Prioritization.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Enhanced HTTP/2 Prioritization

With Enhanced HTTP/2 Prioritization, Cloudflare delivers resources in the optimal order for the fastest experience across all browsers. It also supports control of content delivery when used in conjunction with [Workers](https://developers.cloudflare.com/workers/).

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | No  | Yes      | Yes        | Yes |

## How it works

The speed of loading web content, from the user’s perspective, is dependent on the order in which the resources load. With HTTP/2, by default, Cloudflare will follow the order requested by the browser. This ordering varies from browser to browser, causing a significant difference in performance.

With Enhanced HTTP/2 Prioritization, Cloudflare overrides the default browser behavior to optimize the order of resource delivery, independent of the browser. The greatest improvements will be experienced by visitors using Safari and Edge browsers.

For more details, refer to [the introductory blog post ↗](https://blog.cloudflare.com/better-http-2-prioritization-for-a-faster-web/).

## Enable Enhanced HTTP/2 Prioritization

* [ Dashboard ](#tab-panel-10403)
* [ API ](#tab-panel-10404)

To enable **Enhanced HTTP/2 Prioritization** in the Cloudflare dashboard:

1. Log into the [Cloudflare dashboard ↗](https://dash.cloudflare.com).
2. Select your account and zone.
3. Go to **Speed** \> **Settings**.
4. Go to **Protocol Optimization**.
5. For **Enhanced HTTP/2 Prioritization**, switch the toggle to **On**.

To enable **Enhanced HTTP/2 Prioritization** using the Cloudflare API, send a [PATCH request](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) with `h2_prioritization` as the setting name in the URI path, and the `value` parameter set to `"on"`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/protocol/","name":"Protocol optimization"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/protocol/enhanced-http2-prioritization/","name":"Enhanced HTTP/2 Prioritization"}}]}
```

---

---
title: HTTP/2
description: Serve content over HTTP/2 for multiplexed, lower-latency connections.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# HTTP/2

HTTP/2 uses the TCP transport protocol and TLS to secure communications and improves page load times.

Note

For more background on HTTP/2, visit the [Learning Center ↗](https://www.cloudflare.com/learning/performance/http2-vs-http1.1/).

## Availability

| Free          | Pro | Business | Enterprise |     |
| ------------- | --- | -------- | ---------- | --- |
| Availability  | Yes | Yes      | Yes        | Yes |
| Can customize | No  | Yes      | Yes        | Yes |

## Enable HTTP/2

HTTP/2 is enabled by default for all plans (though it does require an [SSL certificate at Cloudflare’s edge network](https://developers.cloudflare.com/ssl/get-started/)).

## Disable HTTP/2

Domains on Free plans cannot disable Cloudflare's HTTP/2 setting.

* [ Dashboard ](#tab-panel-10405)
* [ API ](#tab-panel-10406)

To disable **HTTP/2** in the dashboard:

1. Log into the [Cloudflare dashboard ↗](https://dash.cloudflare.com).
2. Select your account and zone.
3. Go to **Speed** \> **Settings**.
4. Go to **Protocol Optimization**.
5. For **HTTP/2**, switch the toggle to **Off**.

To disable **HTTP/2** with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `http2` as the setting name in the URI path, and the `value` parameter set to `"off"`.

## ERR\_HTTP2\_PROTOCOL\_ERROR

Requests proxied by Cloudflare may result in an error for visitors with the error code `ERR_HTTP2_PROTOCOL_ERROR` visible in the Developer Tools Console. These errors are usually due to an issue on the origin web server configuration, but might only materialize when requests are proxied by Cloudflare depending on the client browser's behavior. Some possible causes are:

### Malformed HTTP response headers

The origin web server may be sending improperly formatted HTTP response headers.

#### Resolution

Make a request directly to your origin web server and inspect its HTTP response headers for anomalies. Make sure that the field values respect the following requirements:

* [RFC 9110 ↗](https://www.rfc-editor.org/rfc/rfc9110.html#section-5.5)
* [RFC 9113 ↗](https://www.rfc-editor.org/rfc/rfc9113.html#section-8.2.1)
* [RFC 5234 ↗](https://www.rfc-editor.org/rfc/rfc5234#appendix-B.1)

### Compression issues

Examples of compression issues include the origin web server serving gzip encoded compressed content but failing to update the `Content-Length` header, or the origin web server serving broken gzip compressed content.

#### Resolution

You can try to disable compression at your origin web server and rely on Cloudflare to [compress content](https://developers.cloudflare.com/speed/optimization/content/compression/).

You can also review your origin server's compression settings to make sure the compression is working as expected.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/protocol/","name":"Protocol optimization"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/protocol/http2/","name":"HTTP/2"}}]}
```

---

---
title: HTTP/2 to Origin
description: Use HTTP/2 for connections between Cloudflare and your origin.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# HTTP/2 to Origin

A protocol is a set of rules governing the exchange or transmission of data between devices. One of the most important protocols that run on the human-computer interaction layer, where applications can access the network services, is HTTP (Hypertext Transfer Protocol).

HTTP is a well established protocol that has several versions, and each version adds features that improve performance over the older one. HTTP/1.1 and HTTP/2 are widely deployed on the Internet today. HTTP/1.1 has been around for more than a decade, but in 2015 the IETF (Internet Engineering Task Force) introduced HTTP/2, which introduces several features to reduce page load times. To know more about the differences between HTTP/1.1 and HTTP/2, please refer to [HTTP/2 versus HTTP/1.1 ↗](https://www.cloudflare.com/learning/performance/http2-vs-http1.1/).

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

## Disable HTTP/2 to Origin

At Cloudflare, HTTP/2 connection to the origin is enabled by default.

If you wish to disable HTTP/2 to Origin, you can follow these steps:

1. In the Cloudflare dashboard, go to the **Speed** \> **Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/speed/optimization)
2. Go to the **Protocol Optimization** tab and under **HTTP/2 to Origin** set the toggle to **Off**.

## Connection multiplexing

Cloudflare supports HTTP/2 multiplexing from its global edge network to your origin servers. Instead of opening a new TCP connection for every incoming request, multiple HTTP/2 streams share a single long-lived TCP connection. This significantly reduces the cost of connection setup and teardown, improving efficiency and performance between Cloudflare and your origin.

By pooling many requests into fewer TCP connections, Cloudflare lowers the number of active connections your origin must maintain — particularly valuable for backends sensitive to connection overhead or resource limits.

### How it works

When a new request arrives, Cloudflare attempts to reuse an existing HTTP/2 connection to the origin:

* If the connection has not reached its concurrent stream limit, Cloudflare multiplexes the request over that same connection.
* If the stream limit has been reached, Cloudflare opens a new TCP connection as needed.

Connections are kept alive and reused until they become idle or hit their concurrency limit.

#### Connection lifecycle

* **Connection reuse**: Cloudflare maintains persistent (keep-alive) TCP connections to your origin. Reuse continues until the HTTP/2 stream limit is reached or the connection goes idle.
* **Idle timeout (900s)**: If a connection remains idle (no active streams) for 900 seconds, Cloudflare closes it. Attempting to reuse a closed connection may result in a `520` error.
* **Keep-alives**: Cloudflare sends periodic TCP keep-alives to detect unresponsive origins. After two unanswered probes, the connection is reset.  
   * First probe after \~30 seconds of inactivity  
   * Second probe after 15 seconds
* **Connection tear-down**: Connections may also close due to:  
   * Load balancing decisions  
   * Data center or node maintenance  
   * Reaching the maximum concurrency limit  
   * Origin or intermediary network closing idle connections

### Benefits

| Advantage            | Description                                                                                                              |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| Fewer TCP handshakes | Multiple requests share a single long-lived TCP connection, minimizing connection churn.                                 |
| Lower latency        | Eliminates repeated TCP/TLS handshakes, reducing round-trip delays for new requests.                                     |
| Reduced origin load  | Fewer concurrent connections for the origin to manage, easing load on resource-constrained systems.                      |
| Adaptive scaling     | During surges (for example, failovers), Cloudflare reuses available streams first, then opens new connections as needed. |

### Default behavior by plan

| Plan                  | Default State                                 | Max concurrent streams per connection | Configurable? |
| --------------------- | --------------------------------------------- | ------------------------------------- | ------------- |
| Free / Pro / Business | Enabled by default                            | 200                                   | No            |
| Enterprise            | Disabled by default (1 stream per connection) | 1–200+                                | Yes           |

* **Free/Pro/Business**: Multiplexing is automatically enabled. Each connection supports up to 200 concurrent streams.
* **Enterprise**: Multiplexing starts effectively disabled (1 stream). You can enable and configure concurrency per zone (up to 200+ concurrent streams).

### Configuration

Connection multiplexing is enabled by default on Free, Pro and Business zones and uses up to 100 concurrent streams by default. Enterprise plans can explicitly configure the maximum number of concurrent streams (often called the “multiplexing ratio”) for a zone in the dashboard or via API.

Dashboard

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/login) and select your account.
2. Choose the domain that will use HTTP/2 to Origin.
3. Select **Speed > Optimization**.
4. Open the **Protocol Optimization** tab.
5. Under **HTTP/2 to Origin**, select **Configure** and adjust the stream settings as needed.

API

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`
* `Zone Write`

Change Origin H2 Max Streams Setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/origin_h2_max_streams" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": 100

  }'


```

Refer to the [API documentation](https://developers.cloudflare.com/api/python/resources/zones/subresources/settings/methods/edit/) for more information.

Terraform 

```

resource "cloudflare_zone_setting" "example" {

  zone_id    = "<ZONE_ID>"

  setting_id = "origin_h2_max_streams"

  value      = 50

}


```

Note

If your origin does not support multiplexing, enabling HTTP/2 to origin may result in 5xx errors, particularly 520s.

During the HTTP/2 handshake, our edge reads the SETTINGS\_MAX\_CONCURRENT\_STREAMS that your origin advertises, and it will respect that lower limit if your origin is configured with a stricter concurrency cap than Cloudflare's setting. This allows you to control concurrency on a per-origin basis, while still benefiting from Cloudflare's multiplexing framework.

### Timeouts and error codes

| Condition               | Default / Range                   | Error code | Description                                                |
| ----------------------- | --------------------------------- | ---------- | ---------------------------------------------------------- |
| Proxy Read Timeout      | 100s (up to 6000s for Enterprise) | 524        | Origin took too long to respond.                           |
| Proxy Idle Timeout      | 900s (fixed)                      | 520        | Connection closed due to idleness.                         |
| TCP Keep-Alive Interval | 30s initial, 15s between probes   | 520        | After two missed probes, Cloudflare resets the connection. |
| TCP Handshake Timeout   | 19s                               | 522        | Origin did not complete the SYN handshake.                 |
| TCP ACK Timeout         | 90s                               | 522        | Origin stopped acknowledging data.                         |

### Common scenarios

**Failover events**

When traffic shifts suddenly (for example, during origin failover), Cloudflare reuses active connections where possible. If concurrency limits are reached, it opens new ones. Active connection counts may spike temporarily, but overall total connections remain lower than without multiplexing.

**Long-Lived or idle requests**

* If your requests exceed 100 seconds (for example, streaming), increase the Proxy Read Timeout (Enterprise only).
* Origins that close connections faster than 900 seconds may experience connection churn, but Cloudflare automatically reestablishes new connections as needed.

**Potential 5xx errors**

Some 5xx errors, like `520` or `522`, may be related to idle timeouts or unreachable origins. If concurrency is set too high for an underpowered origin, bursts of simultaneous requests can overwhelm it and lead to stream resets or short spikes of 5xx errors. Enterprise customers who encounter this can ask their Cloudflare account team or support to lower the concurrency limit, which reduces how many requests are sent to the origin at the same time and helps prevent overload.

### FAQ

#### Does Cloudflare use a fixed multiplexing ratio?

Free, Pro, and Business plans use 200 concurrent streams per connection. Enterprise users can configure between 1–200+ streams.

#### How does Cloudflare scale connections during spikes or failovers?

Cloudflare first reuses existing keep-alive connections. If they reach concurrency limits, new connections are opened as needed. Even during surges, total connection count is typically lower than without multiplexing.

#### What if my backend is sensitive to parallel requests?

Enterprise users can lower the concurrency limit. Cloudflare also honors your origin's `SETTINGS_MAX_CONCURRENT_STREAMS`, allowing your server to enforce stricter limits. Cloudflare's CDN also provides Cache Locking, which helps avoid multiple parallel requests to your origin during revalidation. Refer to [Revalidation](https://developers.cloudflare.com/cache/concepts/revalidation/) for more information.

#### Can I gradually roll out higher concurrency?

Yes. You can adjust your origin's HTTP/2 settings or Cloudflare's zone setting incrementally to increase concurrency safely.

#### From where does Cloudflare connect to my origin?

Cloudflare operates a flat anycast network. Any data center may connect directly to your origin — there is no L1/L2 hierarchy. Origin connections may come from multiple data centers worldwide.

#### Does Cloudflare prewarm connections to origins?

No. Connections are created on demand and reused where possible. There is no persistent idle pool.

#### How are idle connections managed?

Idle connections are closed after 900 seconds of inactivity. They are not reopened proactively; new connections are created as traffic resumes.

#### Can Cloudflare close active TCP connections?

Only if the origin closes them, a network error occurs, or Cloudflare performs maintenance or load redistribution. There is no hard maximum lifetime for active connections.

## Protocol compatibility

Note that if the origin does not support HTTP/2, Cloudflare will initiate an HTTP/1.1 connection. We connect to servers who announce support of HTTP/2 connections via [ALPN ↗](https://blog.cloudflare.com/introducing-http2).

If you are unsure if your server supports HTTP/2, we suggest checking your origin server's documentation or using a testing tool for HTTP/2 implementation (for example, [h2spec ↗](https://github.com/summerwind/h2spec)).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/protocol/","name":"Protocol optimization"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/protocol/http2-to-origin/","name":"HTTP/2 to Origin"}}]}
```

---

---
title: HTTP/3 (with QUIC)
description: Serve content over HTTP/3 with QUIC for faster connections.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# HTTP/3 (with QUIC)

HTTP/3 uses QUIC, which is a secure-by-default transport protocol. HTTP/3 improves page load times in a similar way to HTTP/2\. However, the QUIC transport protocol solves TCP's head-of-line blocking problem, meaning that performance over lossy networks can be better.

Note

For more background on HTTP/3, visit the [Learning Center ↗](https://www.cloudflare.com/learning/performance/what-is-http3/).

Note

This setting is for connection between the user and Cloudflare. HTTP/3 connection to the origin is not yet supported.

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

## Enable HTTP/3

HTTP/3 is available to all plans (though it does require an [SSL certificate at Cloudflare’s edge network](https://developers.cloudflare.com/ssl/get-started/)).

* [ Dashboard ](#tab-panel-10407)
* [ API ](#tab-panel-10408)

To enable **HTTP/3** in the dashboard:

1. Log into the [Cloudflare dashboard ↗](https://dash.cloudflare.com).
2. Select your account and zone.
3. Go to **Speed** \> **Settings**.
4. Go to **Protocol Optimization**.
5. For **HTTP/3**, switch the toggle to **On**.

To enable **HTTP/3** with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `http3` as the setting name in the URI path, and the `value` parameter set to `"on"`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/protocol/","name":"Protocol optimization"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/protocol/http3/","name":"HTTP/3 (with QUIC)"}}]}
```

---

---
title: Enhanced HTTP/2 Prioritization negatively affects iOS/Safari devices
description: Fix Enhanced HTTP/2 Prioritization issues on iOS and Safari.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Enhanced HTTP/2 Prioritization negatively affects iOS/Safari devices

Occasionally, [Enhanced HTTP/2 Prioritization](https://developers.cloudflare.com/speed/optimization/protocol/enhanced-http2-prioritization/) can negatively affect the experience of visitors using Safari on macOS or any browser on iOS.

These visitors may notice not being able to load the site properly, such as images not displaying or content taking too long to load.

## Solution

If visitors using using Safari on macOS or any browser on iOS are experiencing issues with your site loading properly, try [disabling Enhanced HTTP/2 Prioritization](https://developers.cloudflare.com/speed/optimization/protocol/enhanced-http2-prioritization/#enable-enhanced-http2-prioritization).

Note

Sometimes, [HTTP/2](https://developers.cloudflare.com/speed/optimization/protocol/http2/) will cause **Enhanced HTTP/2 Prioritization** to be re-enabled automatically.

If you notice this happening, also disable **HTTP/2**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/protocol/","name":"Protocol optimization"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/protocol/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":6,"item":{"@id":"/speed/optimization/protocol/troubleshooting/enhanced-http2-prioritization-ios-safari/","name":"Enhanced HTTP/2 Prioritization negatively affects iOS/Safari devices"}}]}
```

---

---
title: Troubleshoot protocol issues
description: Resolve common HTTP/2 and HTTP/3 connection issues.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshoot protocol issues

This guide covers common HTTP/2 and HTTP/3 issues, including origin incompatibility, multiplexing errors, and browser errors, with steps to diagnose and resolve them.

## H2 to Origin - Origin incompatibility

* The origin's `max_concurrent_streams` is negotiated during the handshake process.
* If a `GOAWAY(0)` is received, it is likely due to a server restart or another reason causing the server to refuse new streams.
* For more information, refer to [RFC 9113 - SETTINGS\_MAX\_CONCURRENT\_STREAMS ↗](https://datatracker.ietf.org/doc/html/rfc9113).

## H2 Multiplexing - Origin incompatibility/issues

* Multiplexing issues can arise due to incorrect server configurations.
* Use [netlogs ↗](https://www.chromium.org/developers/design-documents/network-stack/netlog/) to identify `SETTINGS_MAX_CONCURRENT_STREAMS` violations or unexpected `GOAWAY` frames.
* For more information, refer to [Stream Concurrency Issues ↗](https://datatracker.ietf.org/doc/html/rfc9113#name-stream-concurrency).

## Generic browser errors

Common browser errors include:

* `ERR_HTTP2_PROTOCOL_ERROR`
* `ERR_HTTP3_PROTOCOL_ERROR`
* `ERR_QUIC_PROTOCOL_ERROR`

These errors do not necessarily indicate a protocol-level issue. Follow these steps:

1. Attempt reproduction using HTTP/1.1.
2. If the issue persists in HTTP/1.1, address the underlying error before testing HTTP/2 or HTTP/3.
3. If the issue does not persist, analyze netlogs for HTTP/2 or HTTP/3-specific issues.

For more information, refer to [Chromium URL Request Header ↗](https://chromium.googlesource.com/chromium/src/+/HEAD/net/url%5Frequest/url%5Frequest.h).

## Chrome stalls or fails only on HTTP/3

If the issue reproduces only in Chrome over HTTP/3 and disappears when HTTP/3 is disabled, the problem may be related to a browser-side QUIC handling issue rather than your origin server. This is a known Chrome issue ([crbug.com/41161335 ↗](https://issues.chromium.org/issues/41161335)) — Cloudflare's QUIC implementation is not the cause.

Symptoms can include:

* Large downloads stall unexpectedly.
* Pages with many concurrent requests hang for one to three minutes and then fail.
* Chrome reports `ERR_QUIC_PROTOCOL_ERROR` or `ERR_HTTP3_PROTOCOL_ERROR` after the connection stops making progress.
* Issue does not reproduce in Firefox or Safari.
* Issue resolves after disabling QUIC in `chrome://flags`.

### How to isolate the issue

1. Temporarily disable HTTP/3 for the zone.
2. Test the same request again over HTTP/2.
3. If the issue disappears over HTTP/2, capture a NetLog for Chrome and compare the behavior.

**Test immediately:** In Chrome, go to `chrome://flags`, search for "QUIC", set it to **Disabled**, then relaunch Chrome.

### Resolution

If the issue is limited to specific hostnames, you can apply a more targeted workaround: create a Response Header Modification Transform Rule to remove the `Alt-Svc` header for the affected hostname.

1. In the Cloudflare dashboard, go to the Rules **Overview** page.
2. Select **Create rule** \> **Response Header Transform Rule**.
3. Set the matching expression to your hostname: `(http.host eq "example.com")`.
4. Under **Modify response header**, select **Remove** and enter `Alt-Svc` as the header name.

This forces Chrome to use HTTP/2 for that hostname without disabling HTTP/3 globally. However, proxied hostnames can also advertise HTTP/3 through generated HTTPS records, so disabling HTTP/3 for the zone is the most reliable way to force HTTP/2 while you troubleshoot.

After changing `Alt-Svc`, remember that browsers may cache the advertised alternative service for up to 24 hours.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/protocol/","name":"Protocol optimization"}},{"@type":"ListItem","position":5,"item":{"@id":"/speed/optimization/protocol/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":6,"item":{"@id":"/speed/optimization/protocol/troubleshooting/protocol-troubleshooting/","name":"Troubleshoot protocol issues"}}]}
```

---

---
title: Recommendations
description: View personalized speed optimization recommendations for your site.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Recommendations

In the **Recommendations** tab, with one click you can enable all the recommended settings available for your plan. You can enable all the recommended settings at once or you can also just enable the ones you want.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/optimization/","name":"Settings"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/optimization/recommendations/","name":"Recommendations"}}]}
```

---

---
title: Cloudflare SSL/TLS
description: Manage SSL/TLS certificates for encrypted connections between visitors, Cloudflare, and your origin server.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare SSL/TLS

Encrypt your web traffic to prevent data theft and other tampering.

 Available on all plans 

SSL/TLS certificates encrypt traffic between visitors and your website, preventing eavesdropping and data tampering. Because Cloudflare sits between your visitors and your origin server, two certificates can be involved in a single request: an [edge certificate](https://developers.cloudflare.com/ssl/concepts/#edge-certificate) (visitor to Cloudflare) and an [origin certificate](https://developers.cloudflare.com/ssl/concepts/#origin-certificate) (Cloudflare to your server).

Cloudflare automatically issues free certificates through [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) and offers additional options for custom certificate management. Refer to [Get started](https://developers.cloudflare.com/ssl/get-started/) to set up SSL/TLS for your domain.

---

## Features

###  Total TLS 

Universal SSL covers your apex domain and first-level subdomains. Total TLS extends that coverage by automatically issuing certificates for proxied hostnames at any subdomain level.

[ Use Total TLS ](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/) 

###  Delegated DCV 

Before issuing a certificate, a certificate authority (CA) must verify you control the domain. If you manage DNS outside of Cloudflare, you can delegate this verification to Cloudflare so certificate renewals happen automatically.

[ Use Delegated DCV ](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/) 

###  Custom TLS settings 

Specify the minimum TLS version that visitors must use to connect to your website or application, and [restrict cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/)to meet compliance or security requirements.

[ Use Custom TLS settings ](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/minimum-tls/) 

  
For a complete list of SSL/TLS features and their availability by plan, refer to [features and availability](https://developers.cloudflare.com/ssl/reference/all-features/).

---

## Related products

**[Cloudflare DNS](https://developers.cloudflare.com/dns/)** 

When you use Cloudflare DNS, all DNS queries for your domain are answered by Cloudflare's global anycast network. This network delivers performance and global availability.

**[Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/)** 

Cloudflare for SaaS allows you to extend the security and performance benefits of Cloudflare's network to your customers via their own custom or vanity domains.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}}]}
```

---

---
title: Concepts
description: This page defines and articulates key concepts that are relevant to Cloudflare SSL/TLS and are used in the Cloudflare SSL/TLS documentation.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Concepts

This page defines and articulates key concepts that are relevant to Cloudflare SSL/TLS and are used in this documentation. For more concepts and broader descriptions, check out the [Cloudflare Learning Center ↗](https://www.cloudflare.com/learning/ssl/what-is-ssl/).

## SSL/TLS certificate

An SSL/TLS certificate is what enables websites and applications to establish secure connections. With SSL/TLS, a client - such as a browser - can verify the authenticity and integrity of the server it is connecting with, and use encryption to exchange information.

Since [Cloudflare's global network ↗](https://www.cloudflare.com/network/) is at the core of several products and services that Cloudflare offers, what this implies in terms of SSL/TLS is that, instead of only one certificate, there can actually be two certificates involved in a single request: an edge certificate and an origin certificate.

### Edge certificate

The [edge certificates](https://developers.cloudflare.com/ssl/edge-certificates/) are the ones that Cloudflare presents to clients visiting your website or application. You can manage edge certificates through the [Cloudflare Dashboard ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates).

### Origin certificate

[Origin certificates](https://developers.cloudflare.com/ssl/origin-configuration/) guarantee the security and authentication on the other side of the network, between Cloudflare and the origin server of your website or application. Origin certificates are managed on your origin server.

[SSL/TLS encryption modes](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/) control whether and how Cloudflare will use both these certificates, and you can choose between different modes on the [SSL/TLS overview page ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls).

## Validity period

One common aspect of every SSL/TLS certificate is that they must have a fixed expiration date. If a certificate is expired, clients - such as your visitor's browser - will consider that a secure connection cannot be established, resulting in warnings or errors.

Different [certificate authorities (CAs)](#certificate-authority-ca) support different validity periods. Cloudflare works with them to guarantee that both [Universal](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) and [Advanced](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) edge certificates are always renewed.

## Certificate authority (CA)

A [certificate authority (CA)](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) is a trusted third party that generates and gives out SSL/TLS certificates. The CA digitally signs the certificates with their own private key, allowing client devices - such as your visitor's browser - to verify that the certificate is trustworthy.

As explained in the article about [what is an ssl certificate ↗](https://www.cloudflare.com/learning/ssl/what-is-an-ssl-certificate/), this means that, besides not being expired, an SSL/TLS certificate should be issued by a certificate authority (CA) in order to avoid warnings or errors.

## Validation level

SSL/TLS certificates vary in terms of the level to which a CA has validated them. As explained in the article about [types of certificates ↗](https://www.cloudflare.com/learning/ssl/types-of-ssl-certificates/), SSL/TLS certificates can be DV (Domain Validated), OV (Organization Validated) or EV (Extended Validation).

Certificates issued through Cloudflare - [Universal](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/), [Advanced](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/), and [Custom Hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/) certificates - are Domain Validated (DV). You can [upload a custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) if your organization needs OV or EV certificates.

  
## Origin pull

When visitors request content from your website or application, Cloudflare first attempts to [serve content from the cache ↗](https://www.cloudflare.com/learning/cdn/what-is-caching/). If this attempt fails, Cloudflare sends a request back to your origin web server to get the content. This request between Cloudflare and your origin web server is called origin pull.

This relates to the difference between [edge certificates](#edge-certificate) and [origin certificates](#origin-certificate), and also explains why some specifications such as [cipher suites](#cipher-suites) can be set differently depending on whether they refer to the connection between Cloudflare and your visitor's browser or between Cloudflare and your origin server.

## Cipher suites

Besides the authentication and integrity aspects that valid certificates guarantee, the other important aspect of SSL/TLS certificates is encryption. Cipher suites determine the set of algorithms that can be used for encryption/decryption and that will be negotiated during an [SSL/TLS handshake ↗](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/).

For the purpose of this documentation, keep in mind that [cipher suites supported at Cloudflare's network](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/supported-cipher-suites/) may not be the same as [cipher suites presented by Cloudflare to your origin server](https://developers.cloudflare.com/ssl/origin-configuration/cipher-suites/).

## Trust store

The list of [certificate authority (CA)](#certificate-authority-ca) and intermediate certificates that are trusted by operating systems, web browsers or other software that interacts with SSL/TLS certificates is called trust store. Cloudflare maintains its trust store on a public [GitHub repository ↗](https://github.com/cloudflare/cfssl%5Ftrust).

While for most cases you do not have to worry about this list or how it is used when a client checks your SSL/TLS certificate, some features such as [Custom Origin Trust Store](https://developers.cloudflare.com/ssl/origin-configuration/custom-origin-trust-store/), and processes such as [bundle methodologies](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/bundling-methodologies/), are directly related to it.

## Chain of trust

Depending on your organization requirements, or if you have to troubleshoot an issue with your certificates, for example, you might come across the terms root certificate, intermediate certificate and leaf certificate.

These terms refer to the way in which the certificate presented to a client - the leaf certificate - has to be traceable back to a trusted certificate authority (CA) certificate - the [root certificate ↗](https://en.wikipedia.org/wiki/Root%5Fcertificate). This process is structured around a [chain of trust ↗](https://en.wikipedia.org/wiki/Chain%5Fof%5Ftrust).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/concepts/","name":"Concepts"}}]}
```

---

---
title: Get started
description: Set up SSL/TLS encryption between visitors, Cloudflare, and your origin server.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

Set up encrypted connections for your domain by choosing a certificate, selecting an encryption mode, and enforcing HTTPS.

## Before you begin

* [Create an account and register an application](https://developers.cloudflare.com/fundamentals/account/)

## Choose an edge certificate

[Edge certificates](https://developers.cloudflare.com/ssl/concepts/#edge-certificate) are the SSL/TLS certificates that Cloudflare presents to visitors connecting to your domain. Cloudflare offers several types:

* [**Universal certificates**](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/):  
By default, Cloudflare issues — and [renews](https://developers.cloudflare.com/ssl/reference/certificate-validity-periods/#universal-ssl) — free, unshared, publicly trusted SSL certificates to all domains [added to](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) and [activated on](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/) Cloudflare.
* [**Advanced certificates**](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/):  
Use advanced certificates when you want something more customizable than [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) but still want the convenience of SSL certificate issuance and renewal.
* [**Custom certificates**](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/):  
Custom certificates are meant for Business and Enterprise customers who want to use their own SSL certificates.
* [**Keyless certificates**](https://developers.cloudflare.com/ssl/keyless-ssl/) (Enterprise only):  
Keyless SSL allows security-conscious clients to upload their own custom certificates and benefit from Cloudflare, but without exposing their TLS private keys.

For help deciding which certificate type fits your use case, refer to [Edge certificates](https://developers.cloudflare.com/ssl/edge-certificates/).

For SaaS providers

Cloudflare for SaaS allows you to extend the security and performance benefits of Cloudflare's network to your customers via their own custom or vanity domains.

For more details, refer to [Cloudflare for SaaS (managed hostnames)](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/).

## Choose your encryption mode

Once you have chosen your edge certificate, [choose an encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/).

Encryption modes control how Cloudflare manages two separate connections: one between visitors and Cloudflare, and another between Cloudflare and your origin server. Modes range from no encryption to strict validation of your origin certificate. For more context, refer to the [concepts page](https://developers.cloudflare.com/ssl/concepts/#ssltls-certificate).

[Full (strict)](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/) mode — the most secure option — requires a valid, unexpired certificate on your origin server. You can use a certificate from a publicly trusted certificate authority (CA), or generate a free [Origin CA certificate](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/) from Cloudflare. Each encryption mode page lists its specific requirements.

## Enforce HTTPS connections

Even if your application has an active edge certificate, visitors can still access resources over unsecured HTTP connections.

Using various Cloudflare settings, however, you can force all or most visitor connections to [use HTTPS](https://developers.cloudflare.com/ssl/edge-certificates/encrypt-visitor-traffic/).

## SEO considerations

Using HTTPS can improve user trust and may be used as a ranking signal by search engines. For related guidance, refer to [Improve SEO](https://developers.cloudflare.com/fundamentals/performance/improve-seo/).

## Optional - Enable additional features

After you have chosen your encryption mode and enforced HTTPS connections, evaluate the following settings:

* [Edge certificates](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/): Customize different aspects of your edge certificates, from enabling **Opportunistic Encryption** to specifying a **Minimum TLS Version**.
* [Authenticated origin pull](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/): Ensure all requests to your origin server originate from the Cloudflare network.
* [Notifications](https://developers.cloudflare.com/notifications/notification-available/): Set up alerts related to certificate validation status, issuance, renewal, and expiration.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/get-started/","name":"Get started"}}]}
```

---

---
title: Edge certificates
description: Choose the right edge certificate type for your domain based on your use case.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Edge certificates

Edge certificates are the SSL/TLS certificates that Cloudflare presents to visitors connecting to your domain. These certificates secure the encrypted connection between your visitors and Cloudflare.

Use the guidance below to choose the right certificate type for your use case. If you are not familiar with SSL/TLS certificates, refer to [Concepts](https://developers.cloudflare.com/ssl/concepts/).

Note

Occasionally, the Cloudflare dashboard displays a wildcard certificate with only the apex hostname listed (and does not include the wildcard symbol `*`).

This behavior occurs when all of the following conditions are true:

* The zone is on a [subdomain setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/).
* The certificate has a subject or SAN that is a wildcard for the zone's parent domain.

## Use cases

### Simplify issuance and renewal

Managing certificate issuance, renewal, and expiration tracking can be time-consuming. Cloudflare can handle this for you:

* [**Universal SSL**](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/): Automatic, free certificates for your apex domain and first-level subdomains. Provisioned automatically on [full setups](https://developers.cloudflare.com/dns/zone-setups/full-setup/).
* [**Advanced certificates**](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/): Automatic certificates with more control — choose your certificate authority (CA), covered hostnames, and validity period.
* [**Custom certificates**](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/): Upload your own certificates for full control over the CA and [validation level](https://developers.cloudflare.com/ssl/concepts/#validation-level). You handle issuance and renewal.

### Meet cipher suites requirements

A cipher suite is a set of encryption algorithms that a visitor's browser and the server negotiate when establishing a secure connection. Some compliance standards (for example, PCI DSS) require specific cipher suites or prohibit older ones.

With [cipher suites customization](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/), you can set different cipher suites per hostname. For example, you could allow broader compatibility on `www.example.com` for legacy devices while enforcing stricter [compliance standards](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/compliance-status/) on `shop.example.com`.

Custom cipher suites apply to any edge certificate serving that hostname. To use this feature, you must [purchase the Advanced Certificate Manager add-on ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/acm/). Refer to [Customize cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/) for setup instructions.

### Automate domain control validation (DCV)

Before a certificate authority (CA) issues a certificate, it must verify you control the domain. This process is called [domain control validation (DCV)](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/).

If Cloudflare runs your authoritative DNS ([full setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/)), DCV happens automatically. If you manage DNS with another provider ([partial setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/)), you may need to complete DCV manually each time a certificate is issued or renewed.

To automate DCV for partial setups, use [advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) with [delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}}]}
```

---

---
title: Always Use HTTPS
description: Redirect all HTTP requests to HTTPS for your domain.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Always Use HTTPS

Always Use HTTPS redirects all your visitor requests from `http` to `https`, for all subdomains and hosts in your application.

Note

This process does not impact certificate validation. If you use [HTTP DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/), you can still enable Always Use HTTPS.

Cloudflare recommends not performing redirects at your origin web server, as this can cause [redirect loop errors](https://developers.cloudflare.com/ssl/troubleshooting/too-many-redirects/).

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

## Encrypt all visitor traffic

To redirect traffic for all subdomains and hosts in your application, you can enable **Always Use HTTPS**.

Note

If only some parts of your application can support HTTPS traffic, do not enable **Always Use HTTPS** and use a [single redirect](https://developers.cloudflare.com/rules/url-forwarding/single-redirects/) to selectively perform the redirect to HTTPS. Refer to [Redirect admin area requests to HTTPS](https://developers.cloudflare.com/rules/url-forwarding/examples/redirect-admin-https/) for an example.

* [ Dashboard ](#tab-panel-10429)
* [ API ](#tab-panel-10430)

To enable **Always Use HTTPS** in the dashboard:

1. In the Cloudflare dashboard, go to the **SSL/TLS Overview** page.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls)
2. Make sure that your [SSL/TLS encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/off/) is not set to **Off**. When you set your encryption mode to **Off**, the **Always Use HTTPS** option will not be visible in your Cloudflare dashboard.
3. Go to the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page.
4. Turn on **Always Use HTTPS**.

To enable or disable **Always Use HTTPS** with the API:

1. Make sure that your [SSL/TLS encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/off/) **is not** set to **Off**.
2. Send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `always_use_https` as the setting name in the URI path, and the `value` parameter set to your desired setting (`"on"` or `"off"`).

## Limitations

Forcing HTTPS does not resolve issues with [mixed content](https://developers.cloudflare.com/ssl/troubleshooting/mixed-content-errors/), as browsers check the protocol of included resources before making a request. You will need to use only relative links or HTTPS links on pages that you force to HTTPS. Cloudflare can automatically resolve some mixed-content links using our [Automatic HTTPS Rewrites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/automatic-https-rewrites/) functionality.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/always-use-https/","name":"Always Use HTTPS"}}]}
```

---

---
title: Automatic HTTPS Rewrites
description: Fix mixed content by rewriting HTTP URLs to HTTPS in page responses.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Automatic HTTPS Rewrites

Automatic HTTPS Rewrites prevents end users from seeing "mixed content" errors by rewriting URLs from `http` to `https` for resources or links on your web site that can be served with HTTPS.

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

## Additional details

If your site contains links or references to HTTP URLs that are also available securely via HTTPS, Automatic HTTPS Rewrites can help. If you connect to your site over HTTPS and the lock icon is not present, or has a yellow warning triangle on it, your site may contain references to HTTP assets (“mixed content”).

Mixed content is often due to factors not under the website owner’s control such as embedded third-party content or complex content management systems. By rewriting URLs from “http” to “https”, Automatic HTTPS Rewrites simplifies the task of making your entire website available over HTTPS, helping to eliminate mixed content errors and ensuring that all data loaded by your website is protected from eavesdropping and tampering.

Note

For security reasons, this feature will run on URLs pointing to `localhost` if the URL is fetching an active resource (script, iframe, link, object, etc.).

## Enable Automatic HTTPS Rewrites

* [ Dashboard ](#tab-panel-10431)
* [ API ](#tab-panel-10432)

To enable **Automatic HTTPS Rewrites** in the dashboard:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. For **Automatic HTTPS Rewrites**, switch the toggle to **On**.

To enable or disable **Automatic HTTPS Rewrites** with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `automatic_https_rewrites` as the setting name in the URI path, and the `value` parameter set to your desired setting (`"on"` or `"off"`).

Note

To use this feature on specific hostnames - instead of across your entire zone - use a [configuration rule](https://developers.cloudflare.com/rules/configuration-rules/).

## Limitations

Before a rewrite is applied, Cloudflare checks the HTTP resources to ensure they are accessible via HTTPS. If they are not available over HTTPS, Cloudflare cannot rewrite the URL.

Some resources are loaded by JavaScript or CSS via HTTP when the site is loaded in a browser. You will see mixed content warnings in those situations. To determine which URLs do not have HTTPS support, Cloudflare uses data from [EFF’s HTTPS Everywhere ↗](https://www.eff.org/https-everywhere/faq#how-do-i-add-my-own-site-to-https-everywhere) and [Chrome’s HSTS preload list ↗](https://hstspreload.org). If your zone is not on one of these lists, only active content will be rewritten. Passive content (such as images) will not be rewritten and will still cause mixed content errors.

If a third-party domain supports HTTPS and is not rewritten automatically, you can manually change those links to relative links or HTTPS links. Alternatively, you can ask the third-party domain owner to submit their site for inclusion in the HTTPS Everywhere rulesets, which [accept pull requests on GitHub ↗](https://github.com/EFForg/https-everywhere/). For more information on how to fix mixed content errors, refer to [Troubleshooting mixed content errors](https://developers.cloudflare.com/ssl/troubleshooting/mixed-content-errors/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/automatic-https-rewrites/","name":"Automatic HTTPS Rewrites"}}]}
```

---

---
title: Certificate Signing Requests (CSRs)
description: Generate CSRs for use with custom certificates.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Certificate Signing Requests (CSRs)

Generate a Certificate Signing Request (CSR) to get a custom certificate from the Certificate Authority (CA) of your choice while maintaining control of the private key on Cloudflare. The private key associated with the CSR will be generated by Cloudflare and will never leave our network.

A CSR contains information about your domain: your organization name and address, the common name (domain name), and Subject Alternative Names (SANs).

## Availability

| Free         | Pro | Business | Enterprise |                                                                                                                                     |
| ------------ | --- | -------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| Availability | No  | No       | No         | Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) |

## Types of CSRs

You can create two types of CSRs:

* **Zone-level**: Meant only for sign certificates associated with the current zone.
* **Account-level**: Meant for organizations that issue certificates across multiple domains.

## Create and use a CSR

To create a CSR:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. On **Certificate Signing Request (CSR)**, select **Generate**.
3. Choose a **Scope** (only [certain customers](#types-of-csrs) can choose **Account**).
4. Enter relevant information on the form and select **Create**.

To use a CSR:

1. On the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page, select the CSR record you just created under **Certificate Signing Request (CSR)**.
2. Copy (or select **Click to copy**) the value for **Certificate Signing Request**.
3. Obtain a certificate from the Certificate Authority (CA) of your choice using your CSR.
4. When you [upload the custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/) to Cloudflare, select an **Encoding mode** of **Certificate Signing Request (CSR)** and enter the associated value.  
Note  
You will not see the option to adjust your **Encoding Mode** until after you have created a CSR associated with the specific zone or your account.

## Renew a certificate

When you [renew a custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/renewing/), you need to reuse a previously generated CSR.

Note that it is not possible to use a different CSR with the same certificate. In this case, you must upload the certificate as a new certificate, selecting the new CSR.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/certificate-signing-requests/","name":"Certificate Signing Requests (CSRs)"}}]}
```

---

---
title: Certificate Transparency Monitoring
description: Certificate Transparency (CT) Monitoring is an opt-in feature in public beta that aims at improving security by allowing you to double-check any SSL/TLS certificates issued for your domain.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Certificate Transparency Monitoring

Certificate Transparency (CT) Monitoring is an [opt-in](#opt-in-and-out) feature in public beta that aims at improving security by allowing you to double-check any SSL/TLS certificates issued for your domain.

CT Monitoring alerts are triggered not only by Cloudflare processes - including [backup certificates](https://developers.cloudflare.com/ssl/edge-certificates/backup-certificates/) \-, but whenever a certificate that covers your monitored domain is issued by a [Certificate Authority (CA)](https://developers.cloudflare.com/ssl/concepts/#certificate-authority-ca) and added to a public CT log. You can learn more about how this works in the [introductory blog post ↗](https://blog.cloudflare.com/introducing-certificate-transparency-and-nimbus/).

Aspects to consider

* If you use Cloudflare or other services that automatically issue certificates for your domain or subdomains, this may trigger CT Monitoring emails as well.
* If your domain is included in a shared certificate, you may receive notifications for domains or subdomains that do not belong to you but are included as subject alternative names (SANs) together with your domain. You can use a tool like [Certificate Search ↗](https://crt.sh/) to gather more information in such cases.
* CT Monitoring does not detect phishing attempts. For example, for `cloudflare.com`, an alert would not trigger if a certificate was issued for `cloudf1are.com` or `cloud-flare.com`.

---

## Availability

| Free             | Pro                 | Business            | Enterprise                |                           |
| ---------------- | ------------------- | ------------------- | ------------------------- | ------------------------- |
| Availability     | Yes                 | Yes                 | Yes                       | Yes                       |
| Email Recipients | All account members | All account members | Specified email addresses | Specified email addresses |

---

## Opt in and out

Alerts are turned off by default. If you want to receive alerts, go to the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates#ct-alerting-card) page and enable **Certificate Transparency Monitoring**. If you are in a Business or Enterprise zone, select **Add Email**.

To stop receiving alerts, disable **Certificate Transparency Monitoring** or remove your email from the feature card.

---

## Emails to be concerned about

Most certificate alerts are routine. Cloudflare sends alerts whenever a certificate for your domain appears in a log. Certificates expire (and must be reissued), so it is completely normal to receive issuance emails. If your domain is listed in the email, along with reasonable ownership and certificate information, then **no action is required**.

Additionally, you should check whether the certificate was issued through Cloudflare. Cloudflare partners with [multiple CAs](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) to provide certificates. To view all Cloudflare-issued certificates and backup certificates - which require no additional actions - visit the [Edge Certificates page ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) in the dashboard.

You _should_ take action when something is clearly wrong, such as if you:

* Do not recognize the certificate issuer.  
Note  
Cloudflare provisions backup certificates, so you may see a certificate listed that is not in active use for your site. The [Edge Certificates page ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) will show all certificates requested for your site.
* Have recently noticed problems with your website.

---

## How to take action

### Option 1: Contact certificate authorities

Only Certificate Authorities can revoke malicious certificates. If you believe an illegitimate certificate was issued for your domain, contact the Certificate Authority listed as the **Issuer** in the email.

* [GlobalSign support ↗](https://support.globalsign.com/)
* [GoDaddy support ↗](https://www.godaddy.com/contact-us?sp%5Fhp=B)
* [Google Trust Services support ↗](https://pki.goog/faq/)
* [IdenTrust support ↗](https://www.identrust.com/support/support-team)
* [Let's Encrypt support ↗](https://letsencrypt.org/contact/)
* [Sectigo support ↗](https://sectigo.com/support)
* [SSL.com support ↗](https://www.ssl.com/submit-a-ticket/)

### Option 2: Contact domain registrars

Domain registrars may be able to **suspend** potentially malicious domains. If, for example, you notice that a malicious domain was registered through GoDaddy, contact GoDaddy’s support team to see if they can help you. Do the same for other registrars.

### Option 3: Improvise

There are other ways to combat malicious certificates. You can warn your visitors with an on-site notification or ask browser makers (Google for Chrome, etc.) to block these domains.

If someone is attempting to impersonate you online, you should absolutely take action. This is usually difficult to recognize, so exercise caution. **Remember: the vast majority of certificates are not malicious. Only take action if you believe something is wrong.**

---

## HTTP Public Key Pinning

Certificate Transparency Monitoring addresses the same problems as HTTP Public Key Pinning (HPKP), but with [fewer technical issues ↗](https://scotthelme.co.uk/im-giving-up-on-hpkp/).

Cloudflare does not offer or support HPKP and advises against using it with Universal SSL.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/certificate-transparency-monitoring/","name":"Certificate Transparency Monitoring"}}]}
```

---

---
title: Cipher suites
description: Control which encryption algorithms are used in TLS connections to your domain.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cipher suites

Cipher suites are a combination of ciphers used to negotiate security settings during the [SSL/TLS handshake ↗](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/) (and therefore separate from the [SSL/TLS protocol](https://developers.cloudflare.com/ssl/reference/protocols/)).

  
This section covers cipher suites used in connections between visitors and the Cloudflare network. Cipher suites used between Cloudflare and your origin server are configured separately — refer to [Origin server > Cipher suites](https://developers.cloudflare.com/ssl/origin-configuration/cipher-suites/).

[Compliance standards](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/compliance-status/) such as PCI DSS may require specific cipher suites or prohibit older ones, and security testing tools like Qualys SSL Labs may flag Cloudflare's [default configuration](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/recommendations/#legacy-default).

Note

Cloudflare maintains a [public repository of our SSL/TLS configurations ↗](https://github.com/cloudflare/sslconfig) on GitHub, where you can find changes in the commit history.

[RC4 cipher suites ↗](https://blog.cloudflare.com/end-of-the-road-for-rc4/) or [SSLv3 ↗](https://blog.cloudflare.com/sslv3-support-disabled-by-default-due-to-vulnerability/) are no longer supported.

## Cipher suites and edge certificates

Cloudflare's default cipher suites ([Legacy](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/recommendations/)) balance security and compatibility, which means they include older algorithms that security testing tools may flag.

If the default configuration does not meet your requirements, you can [purchase the Advanced Certificate Manager add-on ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/acm/) to [specify more secure cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/).

Cipher suite customization is a hostname-level setting. Once specified, the configuration applies to all edge certificates serving that hostname, regardless of [certificate type](https://developers.cloudflare.com/ssl/edge-certificates/) (universal, advanced, or custom).

## Related SSL/TLS settings

Although configured independently, cipher suites interact with other SSL/TLS settings.

### Minimum TLS Version

You can specify a [minimum TLS version](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/minimum-tls/) that is required for a client to connect to your website or application.

For example, if TLS 1.1 is selected as the minimum, visitors attempting to connect using TLS 1.0 will be rejected while visitors attempting to connect using TLS 1.1, 1.2, or 1.3 (if enabled) will be allowed.

Certain cipher suites are only available in specific TLS versions. If you restrict cipher suites to a [higher security level](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/recommendations/) that excludes older algorithms, you should also adjust your minimum TLS version to match.

[Compliance standards](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/compliance-status/) may also require you to increase the minimum TLS version accepted in connections to your website or application.

### TLS 1.3

You cannot set specific TLS 1.3 ciphers. Instead, you can enable [TLS 1.3](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/tls-13/#enable-tls-13) for your entire zone and Cloudflare will use [all applicable TLS 1.3 cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/supported-cipher-suites/). In combination with this, you can still [disable weak cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/) for TLS 1.0-1.2.

Cloudflare may return the following names for TLS 1.3 cipher suites. This is how they map to [RFC 8446 ↗](https://www.rfc-editor.org/rfc/rfc8446.html) names:

| Cloudflare                    | RFC 8446                        |
| ----------------------------- | ------------------------------- |
| AEAD-AES128-GCM-SHA256        | TLS\_AES\_128\_GCM\_SHA256      |
| AEAD-AES256-GCM-SHA384        | TLS\_AES\_256\_GCM\_SHA384      |
| AEAD-CHACHA20-POLY1305-SHA256 | TLS\_CHACHA20\_POLY1305\_SHA256 |

## Resources

* [ Customize cipher suites ](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/)
* [ Security levels ](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/recommendations/)
* [ Compliance standards ](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/compliance-status/)
* [ Supported cipher suites ](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/supported-cipher-suites/)
* [ Troubleshooting ](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/troubleshooting/)

## Limitations

It is not possible to configure cipher suites for [Cloudflare Pages](https://developers.cloudflare.com/pages/) hostnames.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/","name":"Cipher suites"}}]}
```

---

---
title: Compliance standards
description: Cipher suite compliance with FIPS 140-3, PCI DSS, and other standards.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Compliance standards

Consider the following recommendations on custom [cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/) for when your organization needs to comply with regulatory standards.

Refer to [Customize cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/) to learn how to specify cipher suites at zone level or per hostname.

Warning

Also [enable TLS 1.3](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/tls-13/#enable-tls-13) on your zone and, when opting for [PCI DSS](#pci-dss), make sure to up your [Minimum TLS version](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/minimum-tls/) to `1.2`. Refer to [Cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/) and [TLS protocols](https://developers.cloudflare.com/ssl/reference/protocols/) to learn more.

## PCI DSS

Recommended cipher suites for compliance with the [Payment Card Industry Data Security Standard (PCI DSS) ↗](https://www.pcisecuritystandards.org/standards/pci-dss/). Enhances payment card data security.

Cipher suites list

`AEAD-AES128-GCM-SHA256`[1](#user-content-fn-1), `AEAD-AES256-GCM-SHA384`[2](#user-content-fn-2), `AEAD-CHACHA20-POLY1305-SHA256`[3](#user-content-fn-3), `ECDHE-ECDSA-AES128-GCM-SHA256`, `ECDHE-RSA-AES128-GCM-SHA256`, `ECDHE-ECDSA-AES256-GCM-SHA384`, `ECDHE-RSA-AES256-GCM-SHA384`, `ECDHE-ECDSA-CHACHA20-POLY1305`, `ECDHE-RSA-CHACHA20-POLY1305`

If you are customizing cipher suites via API, refer to [Steps and API examples](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/api/#steps-and-api-examples) for a snippet you can copy with the formatted array.

## FIPS-140-3

Recommended cipher suites for compliance with the [Federal Information Processing Standard (140-3) ↗](https://csrc.nist.gov/pubs/fips/140-3/final). Used to approve cryptographic modules.

Cipher suites list

`AES128-GCM-SHA256`, `AES128-SHA`, `AES128-SHA256`, `AES256-SHA`, `AES256-SHA256`, `DES-CBC3-SHA`, `ECDHE-ECDSA-AES128-GCM-SHA256`, `ECDHE-ECDSA-AES128-SHA`, `ECDHE-ECDSA-AES128-SHA256`, `ECDHE-ECDSA-AES256-GCM-SHA384`, `ECDHE-ECDSA-AES256-SHA384`, `ECDHE-RSA-AES128-GCM-SHA256`, `ECDHE-RSA-AES128-SHA`, `ECDHE-RSA-AES128-SHA256`, `ECDHE-RSA-AES256-GCM-SHA384`, `ECDHE-RSA-AES256-SHA`, `ECDHE-RSA-AES256-SHA384`

If you are customizing cipher suites via API, refer to [Steps and API examples](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/api/#steps-and-api-examples) for a snippet you can copy with the formatted array.

## Footnotes

1. Same as `TLS_AES_128_GCM_SHA256`. Refer to [TLS 1.3 cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/#tls-13) for details. [↩](#user-content-fnref-1)
2. Same as `TLS_AES_256_GCM_SHA384`. Refer to [TLS 1.3 cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/#tls-13) for details. [↩](#user-content-fnref-2)
3. Same as `TLS_CHACHA20_POLY1305_SHA256`. Refer to [TLS 1.3 cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/#tls-13) for details. [↩](#user-content-fnref-3)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/","name":"Cipher suites"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/compliance-status/","name":"Compliance standards"}}]}
```

---

---
title: Customize cipher suites
description: Restrict which cipher suites Cloudflare uses for edge connections.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Customize cipher suites

With an [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) subscription, you can restrict connections between Cloudflare and clients — such as your visitor's browser — to specific [cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/).

You may want to do this to follow specific [recommendations](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/recommendations/), to [disable weak cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/troubleshooting/#ssl-labs-weak-ciphers-report), or to comply with [industry standards](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/compliance-status/).

Customizing cipher suites will not lead to any downtime in your SSL/TLS protection.

Cloudflare for SaaS

If you are a SaaS provider looking to restrict cipher suites for connections to [custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/), this can be configured with a [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) subscription. Refer to [TLS management](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#cipher-suites) instead.

## How it works

Custom cipher suites is a hostname-level setting, which implies that:

* When you customize cipher suites for a zone, this will affect all hostnames within that zone. If you are not familiar with what a Cloudflare zone is, refer to [Fundamentals](https://developers.cloudflare.com/fundamentals/concepts/accounts-and-zones/#zones).
* The configuration is applicable to all edge certificates used to connect to the hostname(s), regardless of the [certificate type](https://developers.cloudflare.com/ssl/edge-certificates/) (universal, advanced, or custom).
* If you need to use a per-hostname cipher suite customization, you must ensure that the hostname is specified on the certificate.

## Scope

Currently, you have the following options:

* Set custom cipher suites for a zone: either [via API](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/api/) or [on the dashboard](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/dashboard/).
* Set custom cipher suites per-hostname: only available [via API](https://developers.cloudflare.com/api/resources/hostnames/subresources/settings/subresources/tls/methods/update/). Refer to the [how-to](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/api/) for details.
* For guidance around custom hostnames, refer to [TLS settings - Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#cipher-suites).

Note

This documentation only refers to connections [between clients and the Cloudflare network](https://developers.cloudflare.com/ssl/concepts/#edge-certificate). For connections between Cloudflare and your origin server, refer to [Origin server > Cipher suites](https://developers.cloudflare.com/ssl/origin-configuration/cipher-suites/).

## Settings priority and ciphers order

Cloudflare uses the [hostname priority logic](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/) to determine which setting to apply.

ECDSA cipher suites are prioritized over RSA, and Cloudflare preserves the specified cipher suites in the order they are set. This means that, if both ECDSA and RSA are used, Cloudflare presents the ECDSA ciphers first - in the order they were set - and then the RSA ciphers, also in the order they were set.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/","name":"Cipher suites"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/","name":"Customize cipher suites"}}]}
```

---

---
title: Customize cipher suites via API
description: Select allowed cipher suites for your zone using the API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Customize cipher suites via API

Cipher suites are a combination of ciphers used to negotiate security settings during the [SSL/TLS handshake ↗](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/) (and therefore separate from the [SSL/TLS protocol](https://developers.cloudflare.com/ssl/reference/protocols/)).

## Prerequisites

Cipher suite customization requires an [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) subscription.

If you are a SaaS provider looking to restrict cipher suites for connections to [custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/), this can be configured with a [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) subscription. Refer to [TLS management](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#cipher-suites) instead.

## Before you begin

Note that:

* Updating the cipher suites will result in certificates being redeployed.
* Cipher suites are used in combination with other [SSL/TLS settings](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/#related-ssltls-settings).
* You cannot set specific TLS 1.3 ciphers. Instead, you can [enable TLS 1.3](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/tls-13/#enable-tls-13) for your entire zone and Cloudflare will use all applicable [TLS 1.3 cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/supported-cipher-suites/).
* Each cipher suite also supports a specific algorithm (RSA or ECDSA) so you should consider the algorithms in use by your edge certificates when making your ciphers selection. You can find this information under each certificate listed on the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page.
* It is not possible to configure minimum TLS version nor cipher suites for [Cloudflare Pages](https://developers.cloudflare.com/pages/) hostnames.
* If you use Windows you might need to adjust the `curl` syntax, refer to [Making API calls on Windows](https://developers.cloudflare.com/fundamentals/api/how-to/make-api-calls/#making-api-calls-on-windows) for further guidance.

Warning

If setting up a per-hostname cipher suite customization, make sure that the hostname is specified on the certificate (instead of being covered by a wildcard). Applying a per-hostname configuration on a wildcard certificate will result in the configuration being applied to all hostnames.

## Steps and API examples

1. Decide which cipher suites you want to specify and which ones you want to disable (meaning they will not be included in your selection).  
Below you will find samples covering the recommended ciphers [by security level](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/recommendations/) and [compliance standards](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/compliance-status/), but you can also refer to the [full list](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/supported-cipher-suites/) of supported ciphers and customize your choice.
2. Log in to the Cloudflare dashboard and get your Global API Key in [**My Profile** \> **API Tokens** ↗](https://dash.cloudflare.com/?to=/:account/profile/api-tokens/).
3. Get the Zone ID from the [Overview page ↗](https://dash.cloudflare.com/?to=/:account/:zone/) of the domain you want to specify cipher suites for.
4. Make an API call to either the [Edit zone setting](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) endpoint or the [Edit TLS setting for hostname](https://developers.cloudflare.com/api/resources/hostnames/subresources/settings/subresources/tls/methods/update/) endpoint, specifying `ciphers` in the URL. List your array of chosen cipher suites in the `value` field.

* [ modern ](#tab-panel-10435)
* [ compatible ](#tab-panel-10436)
* [ pci dss ](#tab-panel-10437)
* [ fips-140-3 ](#tab-panel-10438)

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`

Edit zone setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/ciphers" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": [

        "ECDHE-ECDSA-AES128-GCM-SHA256",

        "ECDHE-ECDSA-CHACHA20-POLY1305",

        "ECDHE-RSA-AES128-GCM-SHA256",

        "ECDHE-RSA-CHACHA20-POLY1305",

        "ECDHE-ECDSA-AES256-GCM-SHA384",

        "ECDHE-RSA-AES256-GCM-SHA384"

    ]

  }'


```

To configure cipher suites per hostname, replace the first two lines by the following:

Terminal window

```

curl --request PUT \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/hostnames/settings/ciphers/{hostname}" \


```

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`

Edit zone setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/ciphers" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": [

        "ECDHE-ECDSA-AES128-GCM-SHA256",

        "ECDHE-ECDSA-CHACHA20-POLY1305",

        "ECDHE-RSA-AES128-GCM-SHA256",

        "ECDHE-RSA-CHACHA20-POLY1305",

        "ECDHE-ECDSA-AES256-GCM-SHA384",

        "ECDHE-RSA-AES256-GCM-SHA384",

        "ECDHE-ECDSA-AES128-SHA256",

        "ECDHE-RSA-AES128-SHA256",

        "ECDHE-ECDSA-AES256-SHA384",

        "ECDHE-RSA-AES256-SHA384"

    ]

  }'


```

To configure cipher suites per hostname, replace the first two lines by the following:

Terminal window

```

curl --request PUT \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/hostnames/settings/ciphers/{hostname}" \


```

Note

For compliance with PCI DSS, also [enable TLS 1.3](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/tls-13/#enable-tls-13) on your zone and make sure to up your [Minimum TLS version](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/minimum-tls/) to `1.2`.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`

Edit zone setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/ciphers" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": [

        "ECDHE-ECDSA-AES128-GCM-SHA256",

        "ECDHE-RSA-AES128-GCM-SHA256",

        "ECDHE-ECDSA-AES256-GCM-SHA384",

        "ECDHE-RSA-AES256-GCM-SHA384",

        "ECDHE-ECDSA-CHACHA20-POLY1305",

        "ECDHE-RSA-CHACHA20-POLY1305"

    ]

  }'


```

To configure cipher suites per hostname, replace the first two lines by the following:

Terminal window

```

curl --request PUT \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/hostnames/settings/ciphers/{hostname}" \


```

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`

Edit zone setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/ciphers" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": [

        "AES128-GCM-SHA256",

        "AES128-SHA",

        "AES128-SHA256",

        "AES256-SHA",

        "AES256-SHA256",

        "DES-CBC3-SHA",

        "ECDHE-ECDSA-AES128-GCM-SHA256",

        "ECDHE-ECDSA-AES128-SHA",

        "ECDHE-ECDSA-AES128-SHA256",

        "ECDHE-ECDSA-AES256-GCM-SHA384",

        "ECDHE-ECDSA-AES256-SHA384",

        "ECDHE-RSA-AES128-GCM-SHA256",

        "ECDHE-RSA-AES128-SHA",

        "ECDHE-RSA-AES128-SHA256",

        "ECDHE-RSA-AES256-GCM-SHA384",

        "ECDHE-RSA-AES256-SHA",

        "ECDHE-RSA-AES256-SHA384"

    ]

  }'


```

To configure cipher suites per hostname, replace the first two lines by the following:

Terminal window

```

curl --request PUT \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/hostnames/settings/ciphers/{hostname}" \


```

### Reset to default values

* [ zone ](#tab-panel-10433)
* [ per-hostname ](#tab-panel-10434)

To reset to the default cipher suites at zone level, use the [Edit zone setting](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) endpoint, specifying `ciphers` as the setting name in the URL, and send an empty array in the `value` field.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`

Edit zone setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/ciphers" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": []

  }'


```

For specific hostname settings, use the [Delete TLS setting for hostname](https://developers.cloudflare.com/api/resources/hostnames/subresources/settings/subresources/tls/methods/delete/) endpoint.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`

Delete TLS setting for hostname

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/hostnames/settings/ciphers/$HOSTNAME" \

  --request DELETE \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

For guidance around custom hostnames, refer to [TLS settings - Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#cipher-suites).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/","name":"Cipher suites"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/","name":"Customize cipher suites"}},{"@type":"ListItem","position":7,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/api/","name":"Customize cipher suites via API"}}]}
```

---

---
title: Customize cipher suites via dashboard
description: Select allowed cipher suites for your zone in the dashboard.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Customize cipher suites via dashboard

Cipher suites are a combination of ciphers used to negotiate security settings during the [SSL/TLS handshake ↗](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/) (and therefore separate from the [SSL/TLS protocol](https://developers.cloudflare.com/ssl/reference/protocols/)).

## Prerequisites

Cipher suite customization requires an [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) subscription.

If you are a SaaS provider looking to restrict cipher suites for connections to [custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/), this can be configured with a [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) subscription. Refer to [TLS management](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#cipher-suites) instead.

## Selection modes

When configuring cipher suites via dashboard, you can use three different selection modes:

* **By security level**: allows you to select between the predefined [Cloudflare recommendations](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/recommendations/) (Modern[1](#user-content-fn-1), Compatible, or Legacy).
* **By compliance standard**: allows you to select cipher suites grouped according to [industry standards](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/compliance-status/) (PCI DSS or FIPS-140-3).
* **Custom**: allows you to individually select the cipher suites you would like to support.

For any of the modes, you should keep in mind the following configuration conditions. If using the **security level** or the **compliance standard** mode, some actions may be blocked and explained referencing these conditions.

Configuration conditions

* Cipher suites are used in combination with other [SSL/TLS settings](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/#related-ssltls-settings).
* You cannot set specific TLS 1.3 ciphers. Instead, you can [enable TLS 1.3](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/tls-13/#enable-tls-13) for your entire zone and Cloudflare will use all applicable [TLS 1.3 cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/supported-cipher-suites/).
* Each cipher suite also supports a specific algorithm (RSA or ECDSA), so you should consider the algorithms in use by your edge certificates when making your ciphers selection. You can find this information under each certificate listed on the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)page. \* It is not possible to configure minimum TLS version nor cipher suites for [Cloudflare Pages](https://developers.cloudflare.com/pages/) hostnames.

## Steps

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. For the **Cipher suites** setting select **Configure**.
3. Choose a mode to select your cipher suites and select **Next**.
4. Select a predefined set of cipher suites or, if you opted for **Custom**, specify which cipher suites you want to allow. Make sure you are aware of how your selection will interact with Minimum TLS version, TLS 1.3, and the certificate algorithm (ECDSA or RSA).
5. Select **Save** to confirm.

Modern or PCI DSS

When used with [TLS 1.3](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/#tls-13), Modern is the same as PCI DSS.

## Footnotes

1. When used with TLS 1.3, Modern is the same as PCI DSS. [↩](#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":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/","name":"Cipher suites"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/","name":"Customize cipher suites"}},{"@type":"ListItem","position":7,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/dashboard/","name":"Customize cipher suites via dashboard"}}]}
```

---

---
title: Security levels
description: Recommended cipher suite security levels for different use cases.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Security levels

Refer to the sections below for three different security levels and how Cloudflare recommends that you set them up if you need to restrict the [cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/) used between Cloudflare and clients that access your website or application.

Refer to [Customize cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/) to learn how to specify cipher suites at zone level or per hostname.

Warning

Before opting for [compatible](#compatible) or [modern](#modern), review the [related SSL/TLS settings](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/#related-ssltls-settings)[1](#user-content-fn-4).

## Modern

Offers the best security and performance, limiting your range of clients to modern devices and browsers. Supports TLS 1.2-1.3 cipher suites. All suites are forward-secret and support authenticated encryption (AEAD).

Cipher suites list

`AEAD-AES128-GCM-SHA256`[2](#user-content-fn-1), `AEAD-AES256-GCM-SHA384`[3](#user-content-fn-2), `AEAD-CHACHA20-POLY1305-SHA256`[4](#user-content-fn-3),`ECDHE-ECDSA-AES128-GCM-SHA256`, `ECDHE-ECDSA-CHACHA20-POLY1305`, `ECDHE-RSA-AES128-GCM-SHA256`, `ECDHE-RSA-CHACHA20-POLY1305`, `ECDHE-ECDSA-AES256-GCM-SHA384`, `ECDHE-RSA-AES256-GCM-SHA384`

If you are customizing cipher suites via API, refer to [Steps and API examples](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/api/#steps-and-api-examples) for a snippet you can copy with the formatted array.

## Compatible

Provides broader compatibility with somewhat weaker security. Supports TLS 1.2-1.3 cipher suites. All suites are forward-secret.

Cipher suites list

`AEAD-AES128-GCM-SHA256`[2](#user-content-fn-1), `AEAD-AES256-GCM-SHA384`[3](#user-content-fn-2), `AEAD-CHACHA20-POLY1305-SHA256`[4](#user-content-fn-3), `ECDHE-ECDSA-AES128-GCM-SHA256`, `ECDHE-ECDSA-CHACHA20-POLY1305`, `ECDHE-RSA-AES128-GCM-SHA256`, `ECDHE-RSA-CHACHA20-POLY1305`, `ECDHE-ECDSA-AES256-GCM-SHA384`, `ECDHE-RSA-AES256-GCM-SHA384`, `ECDHE-ECDSA-AES128-SHA256`, `ECDHE-RSA-AES128-SHA256`, `ECDHE-ECDSA-AES256-SHA384`, `ECDHE-RSA-AES256-SHA384`

If you are customizing cipher suites via API, refer to [Steps and API examples](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/api/#steps-and-api-examples) for a snippet you can copy with the formatted array.

## Legacy (default)

Includes all cipher suites that Cloudflare supports today. Broadest compatibility with the weakest security. Supports TLS 1.0-1.3 cipher suites.

Cipher suites list

`AEAD-AES128-GCM-SHA256`[2](#user-content-fn-1), `AEAD-AES256-GCM-SHA384`[3](#user-content-fn-2), `AEAD-CHACHA20-POLY1305-SHA256`[4](#user-content-fn-3), `ECDHE-ECDSA-AES128-GCM-SHA256`, `ECDHE-ECDSA-CHACHA20-POLY1305`, `ECDHE-RSA-AES128-GCM-SHA256`, `ECDHE-RSA-CHACHA20-POLY1305`, `ECDHE-ECDSA-AES256-GCM-SHA384`, `ECDHE-RSA-AES256-GCM-SHA384`, `ECDHE-ECDSA-AES128-SHA256`, `ECDHE-RSA-AES128-SHA256`, `ECDHE-ECDSA-AES256-SHA384`, `ECDHE-RSA-AES256-SHA384`, `ECDHE-ECDSA-AES128-SHA`, `ECDHE-RSA-AES128-SHA`, `AES128-GCM-SHA256`, `AES128-SHA256`, `AES128-SHA`, `ECDHE-RSA-AES256-SHA`, `AES256-GCM-SHA384`, `AES256-SHA256`, `AES256-SHA`, `DES-CBC3-SHA`

To reset your option to the default, [use an empty array](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/#reset-to-default-values).

## Footnotes

1. Although configured independently, cipher suites interact with **Minimum TLS version** and **TLS 1.3**. [↩](#user-content-fnref-4)
2. Same as `TLS_AES_128_GCM_SHA256`. Refer to [TLS 1.3 cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/#tls-13) for details. [↩](#user-content-fnref-1) [↩2](#user-content-fnref-1-2) [↩3](#user-content-fnref-1-3)
3. Same as `TLS_AES_256_GCM_SHA384`. Refer to [TLS 1.3 cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/#tls-13) for details. [↩](#user-content-fnref-2) [↩2](#user-content-fnref-2-2) [↩3](#user-content-fnref-2-3)
4. Same as `TLS_CHACHA20_POLY1305_SHA256`. Refer to [TLS 1.3 cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/#tls-13) for details. [↩](#user-content-fnref-3) [↩2](#user-content-fnref-3-2) [↩3](#user-content-fnref-3-3)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/","name":"Cipher suites"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/recommendations/","name":"Security levels"}}]}
```

---

---
title: Supported cipher suites
description: Full list of cipher suites supported by Cloudflare edge certificates.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Supported cipher suites

Cloudflare supports the following cipher suites by default. If needed, you can [restrict your website or application](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/) to only use specific cipher suites.

| Cipher name                      | Minimum protocol | [Security recommendation](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/recommendations/) | Cipher suite | IANA name                                           |
| -------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ------------ | --------------------------------------------------- |
| ECDHE-ECDSA-AES128-GCM-SHA256    | TLS 1.2          | Modern, Compatible, Legacy                                                                                                           | \[0xc02b\]   | TLS\_ECDHE\_ECDSA\_WITH\_AES\_128\_GCM\_SHA256      |
| ECDHE-ECDSA-CHACHA20-POLY1305    | TLS 1.2          | Modern, Compatible, Legacy                                                                                                           | \[0xcca9\]   | TLS\_ECDHE\_ECDSA\_WITH\_CHACHA20\_POLY1305\_SHA256 |
| ECDHE-RSA-AES128-GCM-SHA256      | TLS 1.2          | Modern, Compatible, Legacy                                                                                                           | \[0xc02f\]   | TLS\_ECDHE\_RSA\_WITH\_AES\_128\_GCM\_SHA256        |
| ECDHE-RSA-CHACHA20-POLY1305      | TLS 1.2          | Modern, Compatible, Legacy                                                                                                           | \[0xcca8\]   | TLS\_ECDHE\_RSA\_WITH\_CHACHA20\_POLY1305\_SHA256   |
| ECDHE-ECDSA-AES128-SHA256        | TLS 1.2          | Compatible, Legacy                                                                                                                   | \[0xc023\]   | TLS\_ECDHE\_ECDSA\_WITH\_AES\_128\_CBC\_SHA256      |
| ECDHE-ECDSA-AES128-SHA           | TLS 1.0          | Legacy                                                                                                                               | \[0xc009\]   | TLS\_ECDHE\_ECDSA\_WITH\_AES\_128\_CBC\_SHA         |
| ECDHE-RSA-AES128-SHA256          | TLS 1.2          | Compatible, Legacy                                                                                                                   | \[0xc027\]   | TLS\_ECDHE\_RSA\_WITH\_AES\_128\_CBC\_SHA256        |
| ECDHE-RSA-AES128-SHA             | TLS 1.0          | Legacy                                                                                                                               | \[0xc013\]   | TLS\_ECDHE\_RSA\_WITH\_AES\_128\_CBC\_SHA           |
| AES128-GCM-SHA256                | TLS 1.2          | Legacy                                                                                                                               | \[0x9c\]     | TLS\_RSA\_WITH\_AES\_128\_GCM\_SHA256               |
| AES128-SHA256                    | TLS 1.2          | Legacy                                                                                                                               | \[0x3c\]     | TLS\_RSA\_WITH\_AES\_128\_CBC\_SHA256               |
| AES128-SHA                       | TLS 1.0          | Legacy                                                                                                                               | \[0x2f\]     | TLS\_RSA\_WITH\_AES\_128\_CBC\_SHA                  |
| ECDHE-ECDSA-AES256-GCM-SHA384    | TLS 1.2          | Modern, Compatible, Legacy                                                                                                           | \[0xc02c\]   | TLS\_ECDHE\_ECDSA\_WITH\_AES\_256\_GCM\_SHA384      |
| ECDHE-ECDSA-AES256-SHA384        | TLS 1.2          | Compatible, Legacy                                                                                                                   | \[0xc024\]   | TLS\_ECDHE\_ECDSA\_WITH\_AES\_256\_CBC\_SHA384      |
| ECDHE-RSA-AES256-GCM-SHA384      | TLS 1.2          | Modern, Compatible, Legacy                                                                                                           | \[0xc030\]   | TLS\_ECDHE\_RSA\_WITH\_AES\_256\_GCM\_SHA384        |
| ECDHE-RSA-AES256-SHA384          | TLS 1.2          | Compatible, Legacy                                                                                                                   | \[0xc028\]   | TLS\_ECDHE\_RSA\_WITH\_AES\_256\_CBC\_SHA384        |
| ECDHE-RSA-AES256-SHA             | TLS 1.0          | Legacy                                                                                                                               | \[0xc014\]   | TLS\_ECDHE\_RSA\_WITH\_AES\_256\_CBC\_SHA           |
| AES256-GCM-SHA384                | TLS 1.2          | Legacy                                                                                                                               | \[0x9d\]     | TLS\_RSA\_WITH\_AES\_256\_GCM\_SHA384               |
| AES256-SHA256                    | TLS 1.2          | Legacy                                                                                                                               | \[0x3d\]     | TLS\_RSA\_WITH\_AES\_256\_CBC\_SHA256               |
| AES256-SHA                       | TLS 1.0          | Legacy                                                                                                                               | \[0x35\]     | TLS\_RSA\_WITH\_AES\_256\_CBC\_SHA                  |
| DES-CBC3-SHA                     | TLS 1.0          | Legacy                                                                                                                               | \[0x0a\]     | TLS\_RSA\_WITH\_3DES\_EDE\_CBC\_SHA                 |
| AEAD-AES128-GCM-SHA256 \*        | TLS 1.3          | Modern, Compatible, Legacy                                                                                                           | {0x13,0x01}  | TLS\_AES\_128\_GCM\_SHA256                          |
| AEAD-AES256-GCM-SHA384 \*        | TLS 1.3          | Modern, Compatible, Legacy                                                                                                           | {0x13,0x02}  | TLS\_AES\_256\_GCM\_SHA384                          |
| AEAD-CHACHA20-POLY1305-SHA256 \* | TLS 1.3          | Modern, Compatible, Legacy                                                                                                           | {0x13,0x03}  | TLS\_CHACHA20\_POLY1305\_SHA256                     |

\* TLS 1.3 minimum protocol

Ciphers `AEAD-AES128-GCM-SHA256`, `AEAD-AES256-GCM-SHA384`, and `AEAD-CHACHA20-POLY1305-SHA256` are automatically supported by your zone if you [enable TLS 1.3](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/tls-13/#enable-tls-13).

TLS 1.3 uses the same cipher suite space as previous versions of TLS, but defines these cipher suites differently. TLS 1.3 only specifies the symmetric ciphers and cannot be used for TLS 1.2\. Similarly, TLS 1.2 and lower cipher suites cannot be used with TLS 1.3 ([RFC 8446 ↗](https://www.rfc-editor.org/rfc/rfc8446.html)). BoringSSL also hard-codes cipher preferences in this order for TLS 1.3.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/","name":"Cipher suites"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/supported-cipher-suites/","name":"Supported cipher suites"}}]}
```

---

---
title: Troubleshooting
description: Resolve common cipher suite configuration issues.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

If you encounter issues with edge certificate cipher suites, refer to the following scenarios.

## Compatibility with Minimum TLS Version

When you adjust the setting used for your domain's [Minimum TLS Version](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/minimum-tls/), your domain only allows HTTPS connections using that TLS protocol version. As explained in [About cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/#related-ssltls-settings), although configured independently, cipher suites and TLS versions are closely related.

Minimum TLS Version can cause issues if you are not supporting TLS 1.2 ciphers on your domain. If you experience issues, review your domain's [Minimum TLS Version](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/minimum-tls/) setting and Cloudflare's [supported ciphers list](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/supported-cipher-suites/).

### Testing Minimum TLS version with curl

To test supported TLS versions, attempt a request to your website or application while specifying a TLS version.

For example, to test TLS 1.1, use the `curl` command below. Replace `www.example.com` with your Cloudflare domain and hostname.

Terminal window

```

curl https://www.example.com -svo /dev/null --tls-max 1.1


```

If the TLS version you are testing is blocked by Cloudflare, the TLS handshake is not completed and returns an error:

`* error:1400442E:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert`

Note

Local VPN or a device security client may prevent insecure connections using legacy protocols like TLS 1.0\. Make sure to disable such network or security client before running the test on your device.

## Compatibility with certificate encryption

If you [upload a custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/), make sure the certificate is compatible with the chosen cipher suites for your zone or hostname.

For example, if you upload an RSA certificate, your cipher suite selection cannot only support ECDSA certificates.

## Compatibility with Cloudflare Pages

It is not possible to configure minimum TLS version nor cipher suites for [Cloudflare Pages](https://developers.cloudflare.com/pages/) hostnames.

## API requirements for custom hostname certificate

When using the [Edit Custom Hostname endpoint](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/), make sure to include `type` and `method` within the `ssl` object, as well as the `settings` specifications.

Including the `settings` only will result in the error message `The SSL attribute is invalid. Please refer to the API documentation, check your input and try again`.

## TLS 1.3 settings

You cannot set specific TLS 1.3 ciphers. Instead, you can enable [TLS 1.3](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/tls-13/#enable-tls-13) for your entire zone and Cloudflare will use [all applicable TLS 1.3 cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/supported-cipher-suites/). In combination with this, you can still [disable weak cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/) for TLS 1.0-1.2.

## SSL Labs weak ciphers report

If you try to [disable](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/) all of the `WEAK` cipher suites according to what is listed on a [Qualys SSL Labs ↗](https://www.ssllabs.com/ssltest/) report, you might notice that the naming conventions are not the same.

This is because SSL Labs follows RFC cipher naming convention while Cloudflare follows OpenSSL cipher naming convention. The cipher suite names list in the [OpenSSL documentation ↗](https://www.openssl.org/docs/man1.0.2/man1/ciphers.html) may help you map the names.

## Warnings related to CVE-2019-1559

Even though applications on Cloudflare are not vulnerable to [CVE-2019-1559](https://developers.cloudflare.com/ssl/reference/cloudflare-and-cve-2019-1559/), some security scanners may flag your application erroneously.

To remove these warnings, refer to [Customize cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/) and exclude the following ciphers:

* `ECDHE-ECDSA-AES256-SHA384`
* `ECDHE-ECDSA-AES128-SHA256`
* `ECDHE-RSA-AES256-SHA384`

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/","name":"Cipher suites"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/edge-certificates/additional-options/cipher-suites/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: HTTP Strict Transport Security (HSTS)
description: Enforce HTTPS connections with HSTS response headers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# HTTP Strict Transport Security (HSTS)

HSTS protects HTTPS web servers from downgrade attacks. These attacks redirect web browsers from an HTTPS web server to an attacker-controlled server, allowing bad actors to compromise user data and cookies.

HSTS adds an HTTP header that directs [compliant web browsers](https://developers.cloudflare.com/ssl/reference/browser-compatibility/) to:

* Transform HTTP links to HTTPS links
* Prevent users from bypassing SSL browser warnings

Before enabling HSTS, review the [requirements](#requirements).

Note

For more background information on HSTS, see the [introductory blog post ↗](https://blog.cloudflare.com/enforce-web-policy-with-hypertext-strict-transport-security-hsts/).

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

## Requirements

In order for HSTS to work as expected, you need to:

* Have enabled HTTPS before HSTS so browsers can accept your HSTS settings
* Keep HTTPS enabled so visitors can access your site

Once you enabled HSTS, avoid the following actions to ensure visitors can still access your site:

* Changing your DNS records from [Proxied to DNS only](https://developers.cloudflare.com/dns/proxy-status/)
* [Pausing Cloudflare](https://developers.cloudflare.com/fundamentals/manage-domains/pause-cloudflare/) on your site
* Pointing your nameservers away from Cloudflare
* Redirecting HTTPS to HTTP
* Disabling SSL (invalid or expired certificates or certificates with mismatched hostnames)

Warning

If you remove HTTPS before disabling HSTS or before waiting for the duration of the original **Max Age Header** specified in your Cloudflare HSTS configuration, your website becomes inaccessible to visitors for the duration of the Max Age Header or until you enable HTTPS.

## Enable HSTS

* [ Dashboard ](#tab-panel-10439)
* [ API ](#tab-panel-10440)

To enable HSTS using the dashboard:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. For **HTTP Strict Transport Security (HSTS)**, select **Enable HSTS**.
3. Read the dialog and select **I understand**.
4. Select **Next**.
5. Configure the [HSTS settings](#configuration-settings).
6. Select **Save**.

To enable HSTS with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `security_header` as the setting name in the URI path, and specify the `value` object that includes your HSTS settings.

Note

To enable HSTS on a specific subdomain only, configure a [subdomain setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/). Alternatively, you can add the appropriate HSTS header at the origin, or use a [response header transform rule](https://developers.cloudflare.com/rules/transform/response-header-modification/).

## Disable HSTS

To disable HSTS on your website:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. For **HTTP Strict Transport Security (HSTS)**, select **Enable HSTS**.
3. Set the **Max Age Header** to **0 (Disable)**.
4. If you previously enabled the **No-Sniff** header and want to remove it, set it to **Off**.
5. Select **Save**.

## Configuration settings

| Name                                                | Required | Description                                                                                                                                                                                               | Options                                 |
| --------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- |
| Enable HSTS (Strict-Transport-Security)             | Yes      | Serves HSTS headers to browsers for all HTTPS requests. HTTP (non-secure) requests will not contain the header.                                                                                           | Off / On                                |
| Max Age Header (max-age)                            | Yes      | Specifies duration for a browser HSTS policy and requires HTTPS on your website.                                                                                                                          | Disable, or a range from 1 to 12 months |
| Apply HSTS policy to subdomains (includeSubDomains) | No       | Applies the HSTS policy from a parent domain to subdomains. Subdomains are inaccessible if they do not support HTTPS.                                                                                     | Off / On                                |
| Preload                                             | No       | Permits browsers to automatically preload HSTS configuration. Prevents an attacker from downgrading a first request from HTTPS to HTTP. Preload can make a website without HTTPS completely inaccessible. | Off / On                                |
| No-Sniff Header                                     | No       | Sends the X-Content-Type-Options: nosniff header to prevent Internet Explorer and Chrome from automatically detecting a content type other than those explicitly specified by the Content-Type header.    | Off / On                                |

Note

Once HSTS **Preload** is configured, submit requests for addition to each browser’s preload list. Chrome, Firefox/Mozilla, and Safari use the Chrome preload list. A minimum **Max Age Header** of 12 months is required for inclusion in HSTS preload lists.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/http-strict-transport-security/","name":"HTTP Strict Transport Security (HSTS)"}}]}
```

---

---
title: Minimum TLS Version
description: Set the minimum TLS version for connections to your domain.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Minimum TLS Version

Minimum TLS Version only allows HTTPS connections from visitors that support the selected TLS protocol version or newer.

For example, if TLS 1.1 is selected, visitors attempting to connect using TLS 1.0 will be rejected. Visitors attempting to connect using TLS 1.1, 1.2, or 1.3 ([if enabled](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/tls-13/)) will be allowed to connect.

Note

If you are looking to restrict cipher suites, refer to [Customize cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/). For guidance on which TLS version to use, refer to [TLS protocols](https://developers.cloudflare.com/ssl/reference/protocols/).

## Availability

| Free         | Pro                                                                                                                                 | Business                                                                                                                            | Enterprise                                                                                                                          |                                                                                                                                     |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| Availability | Yes                                                                                                                                 | Yes                                                                                                                                 | Yes                                                                                                                                 | Yes                                                                                                                                 |
| Per-hostname | Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) | Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) | Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) | Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) |

It is not possible to configure minimum TLS version for [Cloudflare Pages](https://developers.cloudflare.com/pages/) hostnames.

## How to disable TLS 1.0

You can disable TLS 1.0 by choosing a higher minimum TLS version.

All users can apply this configuration to all hostnames in their zones following the steps under [zone-level](#zone-level).

If you have an [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/#advanced-certificate-manager) subscription, you also have the option to disable TLS 1.0 (or other versions) with a [per-hostname](#per-hostname) setup.

## Setup

Warning

The Minimum TLS version that you set up following these steps does not apply to [R2](https://developers.cloudflare.com/r2/) custom domains. To control the TLS version for R2 custom domains, refer to the [custom domains documentation](https://developers.cloudflare.com/r2/buckets/public-buckets/#minimum-tls-version).

### Zone-level

To manage the TLS version applied to your whole zone when proxied through Cloudflare:

* [ Dashboard ](#tab-panel-10441)
* [ API ](#tab-panel-10442)

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. For **Minimum TLS Version**, select an option.

Use the [Edit zone setting](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) endpoint with `min_tls_version` as the setting name in the URI path, and specify your preferred minimum version in the `value` field.

In the following example, the minimum TLS version for the zone will be set to `1.2`. Replace the zone ID and API token placeholders with your information, and adjust the `value` field with your chosen TLS version.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`

Edit zone setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/min_tls_version" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "id": "min_tls_version",

    "value": "1.2"

  }'


```

### Per-hostname

[Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) users also have the option to specify minimum TLS versions per specific hostnames in their Cloudflare zone.

This is currently only available via the API:

* Use the [Edit TLS setting for hostname](https://developers.cloudflare.com/api/resources/hostnames/subresources/settings/subresources/tls/methods/update/) endpoint to specify different values for `min_tls_version`.
* Use the [Delete TLS setting for hostname](https://developers.cloudflare.com/api/resources/hostnames/subresources/settings/subresources/tls/methods/delete/) endpoint to clear previously defined `min_tls_version` setting.

Cloudflare uses the [hostname priority logic](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/) to determine which setting to apply.

In the following example, the minimum TLS version for a specific hostname will be set to `1.2`. Replace the zone ID, hostname, and authentication placeholders with your information, and adjust the `value` field with your chosen TLS version.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`

Edit TLS setting for hostname

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/hostnames/settings/min_tls_version/$HOSTNAME" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": "1.2"

  }'


```

### Cloudflare for SaaS

If you are a SaaS provider looking to configure minimum TLS version for your custom hostnames, refer to the Cloudflare for SaaS [TLS management](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#minimum-tls-version).

## Test supported TLS versions

To test supported TLS versions, attempt a request to your website or application while specifying a TLS version.

For example, to test TLS 1.1, use the `curl` command below. Replace `www.example.com` with your Cloudflare domain and hostname.

Terminal window

```

curl https://www.example.com -svo /dev/null --tls-max 1.1


```

If the TLS version you are testing is blocked by Cloudflare, the TLS handshake is not completed and returns an error:

`* error:1400442E:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert`

Note

Local VPN or a device security client may prevent insecure connections using legacy protocols like TLS 1.0\. Make sure to disable such network or security client before running the test on your device.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/minimum-tls/","name":"Minimum TLS Version"}}]}
```

---

---
title: Opportunistic Encryption
description: Serve HTTP sites over an encrypted TLS channel.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Opportunistic Encryption

Opportunistic Encryption allows browsers to access HTTP URIs over an encrypted TLS channel. It's not a substitute for HTTPS, but provides additional security for otherwise vulnerable requests.

Use HTTPS when both strong encryption and authentication are required. HTTP Opportunistic Encryption provides a means of enabling TLS when needed for other protocols such as HTTP/2\. It does not provide the same indications of security as HTTPS (the green lock icon in most browser address bars).

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

## Enable Opportunistic Encryption

You do not need to configure your origin web server to support Opportunistic Encryption. All it requires is updating your settings in the Cloudflare dashboard.

* [ Dashboard ](#tab-panel-10443)
* [ API ](#tab-panel-10444)

To enable Opportunistic Encryption in the dashboard:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. For **Opportunistic Encryption**, switch the toggle to **On**.

To adjust your Opportunistic Encryption settings with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `opportunistic_encryption` as the setting name in the URI path, and specify the `value` parameter with your desired setting (`"on"` or `"off"`).

Note

To use this feature on specific hostnames - instead of across your entire zone - use a [configuration rule](https://developers.cloudflare.com/rules/configuration-rules/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/opportunistic-encryption/","name":"Opportunistic Encryption"}}]}
```

---

---
title: TLS 1.3
description: Enable TLS 1.3 for improved performance and security.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# TLS 1.3

TLS 1.3 enables the latest version of the TLS protocol (when supported) for improved security and performance.

## What is TLS 1.3?

TLS 1.3 is the newest, fastest, and most secure version of the [TLS protocol](https://developers.cloudflare.com/ssl/reference/protocols/).

By turning on the TLS 1.3 feature, traffic to and from your website will be served over the TLS 1.3 protocol when supported by clients. TLS 1.3 protocol has improved latency over older versions, has several new features, and is currently supported in all updated major browsers.

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

## Enable TLS 1.3

TLS 1.3 can be activated in the Cloudflare dashboard or through the API:

* [ Dashboard ](#tab-panel-10445)
* [ API ](#tab-panel-10446)

To enable TLS 1.3 in the dashboard:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. For **TLS 1.3**, switch the toggle to **On**.

To adjust your TLS 1.3 settings with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `tls_1_3` as the setting name in the URI path, and set the `value` parameter to your desired setting (`"on"`, `"zrt"` or `"off"`). `zrt` refers to [Zero Round Trip Time Resumption (0-RTT) ↗](https://blog.cloudflare.com/introducing-0-rtt/).

### Troubleshooting

Since TLS 1.3 implementations are relatively new, some failures may occur. If you experience errors, submit a Cloudflare Support ticket with the following information:

* Steps to replicate the issue (if possible)
* Client build version
* Client diagnostic information
* Packet captures

Chrome users should submit a [net-internals trace ↗](https://dev.chromium.org/for-testers/providing-network-details) to Google. Firefox users should [report bugs to Mozilla ↗](https://bugzilla.mozilla.org/home).

## Limitations

You cannot set specific TLS 1.3 ciphers. Instead, you can enable [TLS 1.3](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/tls-13/#enable-tls-13) for your entire zone and Cloudflare will use [all applicable TLS 1.3 cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/supported-cipher-suites/). In combination with this, you can still [disable weak cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/) for TLS 1.0-1.2.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/tls-13/","name":"TLS 1.3"}}]}
```

---

---
title: Total TLS
description: Issue individual certificates for every proxied subdomain.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Total TLS

Total TLS allows Cloudflare to issue individual certificates for your proxied hostnames. These certificates will protect proxied hostnames not covered by [Universal certificates](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/).

Warning

Total TLS certificates follow the Common Name (CN) restriction of 64 characters ([RFC 5280 ↗](https://www.rfc-editor.org/rfc/rfc5280.html)). If you have a hostname that exceeds this length, you can create an [Advanced Certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/#create-a-certificate) via API to cover it.

When issued, these certificates will have a type of **Advanced - Total TLS**, and their default validity period is 90 days.

## Reference

* [ Enable ](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/enable/)
* [ Error messages ](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/error-messages/)

## Availability

Total TLS is available for domains that have purchased [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) and are currently using a [full DNS setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/).

## Limitations

### Hostnames used with other Cloudflare products

Total TLS does not issue certificates for any hostnames used with:

* [Cloudflare Load Balancing](https://developers.cloudflare.com/load-balancing/)
* [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/routing-to-tunnel/)
* [Cloudflare Spectrum](https://developers.cloudflare.com/spectrum/)

You can use other types of certificates or manually [order advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/#create-a-certificate) for these hostnames.

### Deleting certificates

Once you [enable Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/enable/), be careful deleting any Total TLS certificates associated with proxied hostnames.

If you do, our system assumes you want to opt that hostname out of Total TLS certificate and will not order new certificates for the hostname in the future. This behavior applies even if you delete and re-create the hostname's DNS record.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/total-tls/","name":"Total TLS"}}]}
```

---

---
title: Enable
description: Enable Total TLS to issue certificates for all subdomains.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Enable

To enable [Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/) \- which issues individual certificates for your proxied hostnames - follow these instructions:

* [ Dashboard ](#tab-panel-10447)
* [ API ](#tab-panel-10448)

To enable Total TLS in the dashboard:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. For **Total TLS**, switch the toggle to **On** and - if desired - choose an issuing **Certificate Authority**.

To enable Total TLS with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/acm/subresources/total%5Ftls/methods/create/) request with the `enabled` parameter set to your desired setting (`true` or `false`).

You can also specify a desired certificate authority by adding a value to the `certificate_authority` parameter.

## Aspects to consider

* Total TLS certificates follow the Common Name (CN) restriction of 64 characters ([RFC 5280 ↗](https://www.rfc-editor.org/rfc/rfc5280.html)). If you have a hostname that exceeds this length, you can create an [Advanced Certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/#create-a-certificate) via API to cover it.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/total-tls/","name":"Total TLS"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/edge-certificates/additional-options/total-tls/enable/","name":"Enable"}}]}
```

---

---
title: Error messages
description: Error messages you may encounter with Total TLS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Error messages

To help avoid [ERR\_SSL\_VERSION\_OR\_CIPHER\_MISMATCH](https://developers.cloudflare.com/ssl/troubleshooting/version-cipher-mismatch/) errors, Cloudflare automatically shows an error message - `This hostname is not covered by a certificate` \- on proxied DNS records not covered by a TLS certificate.

## Pending domains

If you recently [added your domain](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) to Cloudflare - meaning that your zone is in a [pending state](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/) \- you can often ignore this warning.

Once most domains becomes **Active**, Cloudflare will automatically issue a Universal SSL certificate, which will provide SSL/TLS coverage and remove the warning message.

Note

Since there are a few nuances to certificate coverage and issuance timing, review [Enable Universal SSL certificates](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/enable-universal-ssl/) to make sure your domain will receive SSL/TLS coverage automatically.

## Active domains

If your zone is already active on Cloudflare, this warning identifies subdomains that are not covered by your current SSL/TLS certificate.

By default, Cloudflare [Universal SSL certificates](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) only cover your apex domain and one level of subdomain.

| Hostname                 | Covered by Universal certificate? |
| ------------------------ | --------------------------------- |
| example.com              | Yes                               |
| www.example.com          | Yes                               |
| docs.example.com         | Yes                               |
| dev.docs.example.com     | No                                |
| test.dev.api.example.com | No                                |

To prevent insecure connections on a multi-level subdomain, do one of the following:

* Enable [Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/), which automatically issues individual certificates to your proxied hostnames not covered by a Universal certificate.
* Order an [Advanced Certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/) covering the subdomain.
* Upload a [Custom Certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) covering the subdomain.

If none of these solutions work, you could also remove the multi-level subdomain.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/additional-options/total-tls/","name":"Total TLS"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/edge-certificates/additional-options/total-tls/error-messages/","name":"Error messages"}}]}
```

---

---
title: Advanced certificates
description: Order advanced certificates with custom SANs, validity periods, and CAs.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Advanced certificates

Use advanced certificates when you want something more customizable than [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) but still want the convenience of SSL certificate issuance and renewal.

  
To order advanced certificates, you must purchase the Advanced Certificate Manager add-on. This add-on also unlocks the features listed below.

## What the add-on includes

Advanced Certificate Manager allows you to:

* Order advanced certificates that can:  
   * Include up to 50 hosts as covered hostnames (the zone apex must be one of these 50).  
   * Cover more than one level of subdomain.  
   * Be issued by the certificate authority (CA) you choose.  
   * Use your preferred validation method.  
   * Have the validity period you choose.
* Automate domain control validation (DCV) for zones on a [CNAME setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/) using [delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/).
* Enable [Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/) to automatically protect proxied hostnames.
* Select a [custom trust store](https://developers.cloudflare.com/ssl/origin-configuration/custom-origin-trust-store/) for origin authentication.
* Control [cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/) and [per-hostname minimum TLS version](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/minimum-tls/#per-hostname).

Note

Enterprise customers can also purchase a subscription for Advanced Certificate Manager, which allows them to add up to 100 edge certificates per zone.

Note

On Partial zones, Universal SSL is provisioned per proxied hostname regardless of subdomain depth. If your only reason for considering an advanced certificate is to cover subdomains beyond the first level, Universal SSL may already be sufficient — though you'll need to proxy and validate each new hostname individually as it is added.

## Availability

| Free         | Pro         | Business    | Enterprise  |             |
| ------------ | ----------- | ----------- | ----------- | ----------- |
| Availability | Paid add-on | Paid add-on | Paid add-on | Paid add-on |

Note

Eligible enterprise customers can preview this product as a [non-contract service](https://developers.cloudflare.com/billing/understand/preview-services/), which provides full access, free of metered usage fees, limits, and certain other restrictions.

## Limitations

Advanced certificates do not apply to [Cloudflare Pages](https://developers.cloudflare.com/pages/) or [R2](https://developers.cloudflare.com/r2/) custom domains. Due to [certificate prioritization](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/), these products use Cloudflare for SaaS certificates instead.

Advanced certificates are [Domain Validated (DV)](https://developers.cloudflare.com/ssl/concepts/#validation-level). If your organization needs Organization Validated (OV) or Extended Validation (EV) certificates, refer to [Custom certificates](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/).   

Advanced certificates cover hostnames within a single domain. If you need a certificate that spans multiple domains (a multi-domain certificate), use [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/). For architecture guidance, refer to [Leveraging Cloudflare for your SaaS applications](https://developers.cloudflare.com/reference-architecture/design-guides/leveraging-cloudflare-for-your-saas-applications/).

Note

Cloudflare does not support HTTP public key pinning (HPKP) for universal, advanced, or custom hostname certificates. For details and recommended alternatives, refer to [Certificate pinning](https://developers.cloudflare.com/ssl/reference/certificate-pinning/).

## Multi-level subdomain support

Advanced Certificate Manager supports deep, multi-level subdomains (for example, `api.staging.example.com`). There is no arbitrary limit on the number of subdomain levels, but you must consider the following constraints.

Note

If you want to automatically issue certificates for all proxied hostnames without manually specifying each one, enable [Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/).

### Domain name length limits

These limits are defined by internet standards ([RFC 1035 ↗](https://www.rfc-editor.org/rfc/rfc1035) and [RFC 5280 ↗](https://www.rfc-editor.org/rfc/rfc5280)) and apply to all certificates, regardless of the certificate authority:

* **Total domain length**: The entire domain name cannot exceed 253 characters.
* **Label length**: Each individual level (the text between dots) cannot exceed 63 characters.
* **Common Name (CN) length**: The Common Name field of a certificate cannot exceed 64 characters. If a hostname on your certificate exceeds 64 characters, you must order the certificate via the [API](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/create/) and set the `cloudflare_branding` option to `true`. This places `sni.cloudflaressl.com` in the CN field and your long hostname in the SAN field. The dashboard does not support ordering certificates with hostnames longer than 64 characters.

### Wildcard coverage

Wildcard certificates only cover **one subdomain level**:

* A certificate for `*.example.com` covers `www.example.com` and `api.example.com` but **not** `api.staging.example.com`.
* To cover multiple levels, you must explicitly add a wildcard for each level to your certificate (for example, `*.example.com`, `*.staging.example.com`).

### Hostnames per certificate

A single advanced certificate can include up to **50 hosts** (SANs) total. The zone apex must be one of these 50, leaving room for up to 49 additional hostnames or wildcards.

### Consistency across certificate authorities

The character-length limits above (253-character total, 63-character label, 64-character CN) are defined by IETF standards ([RFC 1035 ↗](https://www.rfc-editor.org/rfc/rfc1035), [RFC 5280 ↗](https://www.rfc-editor.org/rfc/rfc5280)) and apply uniformly across all CAs. Other constraints, such as the per-certificate SAN count and supported validity periods, are Cloudflare advanced certificates limits or vary by CA. Refer to [Certificate authorities](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) for CA-specific details.

## Related resources

* [ Manage advanced certificates ](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/)
* [ API commands ](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/api-commands/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/advanced-certificate-manager/","name":"Advanced certificates"}}]}
```

---

---
title: API commands
description: API commands for managing advanced certificates.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# API commands

Use the following API commands to manage advanced certificates. If you are using our API for the first time, review our [API documentation](https://developers.cloudflare.com/fundamentals/api/).

| Command                                                                                                                                                                                       | Method | Endpoint                                             | Additional notes                                                                            |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| [Order advanced certificate](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/create/)                                                            | POST   | zones/<<ZONE\_ID>>/ssl/certificate\_packs/order      |                                                                                             |
| [Restart certificate validation](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/edit/)                                                          | PATCH  | zones/<<ZONE\_ID>>/ssl/certificate\_packs/<<ID>>     | For a Certificate Pack in a validation\_timed\_out status.                                  |
| [Delete certificate pack](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/delete/)                                                               | DELETE | zones/<<ZONE\_ID>>/ssl/certificate\_packs/<<ID>>     |                                                                                             |
| [List certificate packs in a zone](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/list/)                                                        | GET    | zones/<<ZONE\_ID>>/ssl/certificate\_packs?status=all | This API call returns all certificate packs for a domain (Universal, Custom, and Advanced). |
| List Cipher Suite settings: [Get zone setting](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/get/) with ciphers as the setting name in the URI path     | GET    | zones/<<ZONE\_ID>>/settings/ciphers                  |                                                                                             |
| Change Cipher Suite settings: [Edit zone setting](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) with ciphers as the setting name in the URI path | PATCH  | zones/<<ZONE\_ID>>/settings/ciphers                  | To restore default settings, send a blank array in the value parameter.                     |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/advanced-certificate-manager/","name":"Advanced certificates"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/advanced-certificate-manager/api-commands/","name":"API commands"}}]}
```

---

---
title: Manage advanced certificates
description: Learn how to create, delete and perform other operations to manage your Cloudflare Advanced SSL certificates.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Manage advanced certificates

## Create a certificate

If you are using an existing [Universal SSL certificate](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/), Cloudflare will automatically replace this certificate once you finish ordering your advanced certificate.

Once you order a certificate, you can review the [certificate's status](https://developers.cloudflare.com/ssl/reference/certificate-statuses/) on the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page or via the API with a [GET request](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/list/).

* [ Dashboard ](#tab-panel-10449)
* [ API ](#tab-panel-10450)

To create a new advanced certificate in the dashboard:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. Select **Order Advanced Certificate**.
3. If Cloudflare does not have your billing information, you will need to enter that information.
4. Enter the following information:  
   * Certificate authority  
   * Certificate hostnames  
         * For hostnames longer than 64 characters, use the API.  
   * Validation method  
   * Certificate validity period
5. Select **Save**.

To create a new certificate using the API, send a [POST request](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/create/) to the Cloudflare API.

If you need certificates for hostnames longer than 64 characters ([RFC 5280 ↗](https://www.rfc-editor.org/rfc/rfc5280.html)), set the `cloudflare_branding` option to `true`. This will add `sni.cloudflaressl.com` in the Common Name (CN) field and will include the long hostname as a part of the Subject Alternative Name (SAN).

Warning

The available options for **Validation method** and **Certificate Validity Period** may vary depending on the certificate authority you choose and the hostnames that you include in your Advanced certificate order.

---

## Delete a certificate

* [ Dashboard ](#tab-panel-10451)
* [ API ](#tab-panel-10452)

To delete an advanced certificate in the dashboard:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. Select a certificate.
3. Select **Delete Certificate**.

To delete a certificate using the API, send a [DELETE request](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/delete/) to the Cloudflare API.

---

## Restart validation

To restart validation for a certificate in a `validation_timed_out` status, send a [PATCH request](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/edit/) to the API.

---

## Restrict cipher suites

Cipher suites are a combination of ciphers used to negotiate security settings during the [SSL/TLS handshake ↗](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/) (and therefore separate from the [SSL/TLS protocol](https://developers.cloudflare.com/ssl/reference/protocols/)).

For more details, refer to [Customize cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/).

---

## Perform domain control validation (DCV)

Before a certificate authority (CA) will issue a certificate for a domain, the requester must prove they have control over that domain. This process is known as domain control validation (DCV).

  
Normally, you only need to update DCV if you have your application on a partial setup (Cloudflare does not run your authoritative nameservers).

For more information about DCV, refer to [DCV methods](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/).

---

## Set up alerts

You can configure alerts to receive notifications for changes in your certificates.

Advanced Certificate Alert

**Who is it for?**

Customers with [advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) that want to be alerted on validation, issuance, renewal, and expiration of certificates.

**Other options / filters**

None.

**Included with**

When an advanced certificate is validated, issued, renewed, or expired.

**What should you do if you receive one?**

Action only needed if notification is about a certificate that failed to be issued. Refer to [SSL expired or SSL mismatch errors](https://developers.cloudflare.com/ssl/troubleshooting/version-cipher-mismatch/) for more information.

Refer to [Cloudflare Notifications](https://developers.cloudflare.com/notifications/get-started/) for more information on how to set up an alert.

---

## Advanced certificate renewal

The certificate validity period you choose determines when the auto renewal will start for your certificate. For details, refer to [Validity period and renewal](https://developers.cloudflare.com/ssl/reference/certificate-validity-periods/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/advanced-certificate-manager/","name":"Advanced certificates"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/","name":"Manage advanced certificates"}}]}
```

---

---
title: Backup certificates
description: How Cloudflare issues backup certificates for redundancy.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Backup certificates

If Cloudflare is providing [authoritative DNS](https://developers.cloudflare.com/dns/zone-setups/full-setup/) for your domain, Cloudflare will issue a backup [Universal SSL certificate](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) for every standard Universal certificate issued.

Backup certificates are wrapped with a different private key and issued from a different Certificate Authority — either Google Trust Services, Let's Encrypt, Sectigo, or SSL.com — than your domain's primary Universal SSL certificate.

These backup certificates are not normally deployed, but they will be deployed automatically by Cloudflare in the event of a certificate revocation or key compromise.

For additional details, refer to the [introductory blog post ↗](https://blog.cloudflare.com/introducing-backup-certificates/).

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |
| Can opt out? | No  | No       | No         | Yes |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/backup-certificates/","name":"Backup certificates"}}]}
```

---

---
title: Add CAA records
description: Add CAA DNS records to control which CAs can issue certificates.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Add CAA records

A Certificate Authority Authorization (CAA) DNS record specifies which certificate authorities (CAs) are allowed to issue certificates for a domain. This record reduces the chance of unauthorized certificate issuance and promotes standardization across your organization.

  
For additional security, set up [Certificate Transparency Monitoring](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/certificate-transparency-monitoring/) as well.

Note

For more technical details about CAA records, refer to the [introductory blog post ↗](https://blog.cloudflare.com/caa-of-the-wild/).

## Who should create CAA records?

You should [create CAA records](#create-caa-records) in Cloudflare if each of the following is true:

* You uploaded your own custom origin server certificate (not provisioned by Cloudflare).
* That certificate was issued by a CA (not self-signed).
* Your domain is on a [full setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/) (not a [CNAME setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup)).
* When adding new [Custom Hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/) and your customer has existing CAA records. In this case, ask your customer to remove the existing CAA records or add the missing CAA record.

## CAA records added by Cloudflare

Cloudflare adds CAA records automatically in the following situations:

* When you have [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) and add any CAA records to your zone.
* When you have [advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) and add any CAA records to your zone.

These records make sure Cloudflare can still issue Universal certificates on your behalf.

Subdomain zones caveat

CAA records are inherited. This means that, if you are using a [subdomain setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/) \- with `subdomain.example.com` on Cloudflare but `example.com` on a different DNS provider -, you should make sure that the parent domain (`example.com`) either has CAA records that allow [Cloudflare's partner CAs](https://developers.cloudflare.com/ssl/reference/certificate-authorities/), or has no CAA records at all.

If Cloudflare has automatically added CAA records on your behalf, these records will not appear in the Cloudflare dashboard. However, if you run a command line query using `dig`, you can see any existing CAA records, including those added by Cloudflare (replacing `example.com` with your own domain on Cloudflare):

Terminal window

```

➜  ~ dig example.com caa +short


# CAA records added by Google Trust Services

0 issue "pki.goog; cansignhttpexchanges=yes"

0 issuewild "pki.goog; cansignhttpexchanges=yes"


# CAA records added by Let's Encrypt

0 issue "letsencrypt.org"

0 issuewild "letsencrypt.org"


# CAA records added by SSL.com

0 issue "ssl.com"

0 issuewild "ssl.com"


# CAA records added by Sectigo

0 issue "sectigo.com"

0 issuewild "sectigo.com"


```

Note

This list is not exhaustive, and other CAs might be added or removed for operational reasons.

## Create CAA records

Create a CAA record for each Certificate Authority (CA) that you plan to use for your domain.

* [ Dashboard ](#tab-panel-10453)
* [ API ](#tab-panel-10454)

To add a CAA record in the dashboard,

1. In the Cloudflare dashboard, go to the **DNS Records** page.  
[ Go to **Records** ](https://dash.cloudflare.com/?to=/:account/:zone/dns/records)
2. Select **Add record**.
3. For **Type**, select **CAA**.
4. For **Name**, type your domain.
5. Choose a **Tag**, which specifies the behavior associated with the record.
6. For **CA domain name**, enter the CA name.
7. Select **Save**.
8. Repeat for each CA associated with your domain.

To create a CAA record via the API, use this [POST endpoint](https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/).

Once you have finished creating all the records, you can review them in the list of records appearing under the DNS Records panel.

## Certificate authorities and required CAA values

If you have CAA records on your domain, they must permit the certificate authority (CA) that Cloudflare uses. For the required CAA values for each CA Cloudflare may use, refer to [Certificate authorities](https://developers.cloudflare.com/ssl/reference/certificate-authorities/#caa-records).

### CNAME chain CAA records

CAA records on a CNAME target also apply. If your hostname CNAMEs to a domain whose zone has restrictive CAA records, those records take precedence — even if your own domain has no CAA records.

Check CAA at all levels of your CNAME chain:

Terminal window

```

dig yourdomain.com CAA +short

dig cname-target.com CAA +short


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/caa-records/","name":"Add CAA records"}}]}
```

---

---
title: Domain control validation (DCV)
description: Understand when domain control validation is required and when Cloudflare handles it automatically.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Domain control validation (DCV)

Before a certificate authority (CA) will issue a certificate for a domain, the requester must prove they have control over that domain. This process is known as domain control validation (DCV).

If DCV is not completed, the CA cannot issue or renew the certificate, and visitors to your site will see SSL/TLS errors.

Note

Refer to [Domain control validation flow](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/dcv-flow/) to learn more about the steps and parties involved in the DCV process.

For [custom certificates](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/), you handle DCV directly with the CA when requesting or renewing the certificate.

For certificates issued through Cloudflare, whether DCV is automatic depends on your DNS setup.

---

## Full DNS setup - no action required

If your domain is on a [**full setup**](https://developers.cloudflare.com/dns/zone-setups/full-setup/) — meaning that Cloudflare runs your authoritative nameservers — Cloudflare handles DCV automatically on your behalf using a TXT record. For more details, refer to [Enable Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/enable-universal-ssl/#full-dns-setup).

---

## Partial DNS setup - action sometimes required

If your application is on a [partial DNS setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/) — meaning that Cloudflare does not run your authoritative nameservers — you may need to perform additional steps to complete DCV.

### Non-wildcard certificates

If every hostname on a non-wildcard certificate is [proxying traffic](https://developers.cloudflare.com/dns/proxy-status/) through Cloudflare and the DCV method is [HTTP](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/http/), Cloudflare can automatically complete DCV on your behalf.

This applies to customers using [Universal](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) or [Advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/).

If one of the hostnames on the certificate is not proxying traffic through Cloudflare, certificate issuance and renewal will vary based on the type of certificate you are using:

* **Universal**: Perform DCV using one of the available [methods](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/).
* **Advanced**: In most cases, you can opt for [Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/), which greatly simplifies certificate management.

Tip

If all hostnames are proxied and non-wildcard but you are using [TXT](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/txt/) as DCV method for advanced certificates, also consider [Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/) to simplify the process.

### Wildcard certificates

For wildcard hostname certificates, certificate issuance and renewal varies based on the type of certificate you are using:

* **Universal**: Perform DCV using [TXT validation method](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/txt/).
* **Advanced**: In most cases, you can opt for [Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/), which greatly simplifies certificate management.

If you cannot use Delegated DCV, you need to use [TXT based DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/txt/) for certificate issuance and renewal. This means you will need to place one TXT DCV token for every hostname on the certificate. If one or more of the hostnames on the certificate fails to validate, the certificate will not be issued or renewed.

This means that a wildcard certificate covering `example.com` and `*.example.com` will require two DCV tokens to be placed at the authoritative DNS provider. Similarly, a certificate with five hostnames in the SAN (including a wildcard) will require five DCV tokens to be placed at the authoritative DNS provider.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/","name":"Domain control validation (DCV)"}}]}
```

---

---
title: Domain control validation flow
description: Consider the steps that have to take place before the DCV process is completed and certificate authorities can issue SSL/TLS certificates.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Domain control validation flow

To obtain [Universal](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/), [Advanced](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/), and [Custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/) certificates, Cloudflare partners with different publicly trusted [certificate authorities (CAs)](https://developers.cloudflare.com/ssl/reference/certificate-authorities/).

However, every time a CA is requested to issue or renew a certificate, the requester must prove that they have control over the domain. That is when the DCV process takes place, with the proof usually consisting of placing an HTTP token at a standard URL path (`/.well-known/pki-validation`), or placing a TXT record at the authoritative DNS provider.

## Where Cloudflare sits in the DCV process

For the use cases mentioned above, there are three different parties involved in the process:

* The website or application for which the certificate is issued.
* The requester (Cloudflare).
* The CA that processes the request.

## Steps in the process

In summary, five steps have to succeed after Cloudflare requests a CA to issue or renew a certificate:

1. Cloudflare receives the DCV tokens from the CA.
2. Cloudflare either places the tokens on your behalf ([Full DNS setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/), [Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/)), or makes the tokens available for you to place them.
3. Cloudflare polls the validation URLs to check for the tokens.
4. After Cloudflare can confirm that the tokens are placed via multiple DNS resolvers, the CA is asked to check as well.
5. If the CA can confirm the tokens are placed, the certificate gets issued. If the CA cannot confirm the tokens are placed, the certificate is not issued and the tokens are no longer valid.

## Aspects to consider

* Settings that interfere with the validation URLs - firewall blocks or misconfigured DNSSEC, for example - can cause issues with your certificate issuance or renewal. Refer to the [troubleshooting guide](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/troubleshooting/).
* When your certificate is in `pending_validation` and valid tokens are in place, some security features targeting your zone's path for `/.well-known/*` can be automatically bypassed.
* Certificate authority authorization (CAA) records may block certificate issuance. Refer to [CAA records](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/).

### DCV tokens

DCV tokens are generated and controlled by the CA and not by Cloudflare. You can find further technical specification of how they work in [RFC 8555 ↗](https://www.rfc-editor.org/rfc/rfc8555#section-7.1.5).

* As mentioned in [Step 5](#steps-in-the-process), DCV tokens will change upon verification failures. For example, if a DCV check fails because of a DNSSEC issue, the certificate order is no longer valid and Cloudflare must start a new certificate request. Since tokens cannot be reused, a new token is required.
* DCV tokens also have [validity periods](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/validation-backoff-schedule/). If you are handling the DCV process manually, it is recommended that you place the tokens as soon as the certificate is up for renewal. Otherwise, the tokens may expire and new tokens will be required.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/","name":"Domain control validation (DCV)"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/dcv-flow/","name":"Domain control validation flow"}}]}
```

---

---
title: Methods
description: Review different methods to perform Domain Control Validation when using Cloudflare SSL/TLS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Methods

Before a certificate authority (CA) will issue a certificate for a domain, the requester must prove they have control over that domain. This process is known as domain control validation (DCV).

## Perform DCV

For details on each method available for DCV, refer to the following resources:

* [ Delegated ](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/)
* [ TXT ](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/txt/)
* [ HTTP ](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/http/)

Note

For guidance on when you need to perform DCV, refer to [Domain Control Validation](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/).

---

## Verify DCV status

To verify the [DCV status](https://developers.cloudflare.com/ssl/reference/certificate-statuses/) of a certificate, either monitor the certificate's status on the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page or use the [Verification Status endpoint](https://developers.cloudflare.com/api/resources/ssl/subresources/verification/methods/get/).

A status of `active` means that the certificate has been deployed to Cloudflare’s global network and will be served as soon as HTTP traffic is proxied to Cloudflare.

## Update DCV methods

You cannot update the DCV method for an active certificate. To update the DCV method for a subdomain, wait until the DCV expires and then change the DCV method.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/","name":"Domain control validation (DCV)"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/methods/","name":"Methods"}}]}
```

---

---
title: Delegated
description: Delegate domain control validation to Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Delegated

Delegated DCV allows zones with [partial DNS setups](https://developers.cloudflare.com/dns/zone-setups/partial-setup/) \- meaning authoritative DNS is not provided by Cloudflare - to delegate the DCV process to Cloudflare.

DCV Delegation requires you to place a one-time record that allows Cloudflare to auto-renew all future certificate orders, so that there’s no manual intervention at the time of the renewal.

Note

DCV Delegation will not work with Universal Certificates and requires the use of an [Advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/).

## Availability

| Free         | Pro                                                                                                                                 | Business                                                                                                                            | Enterprise                                                                                                                          |                                                                                                                                     |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| Availability | Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) | Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) | Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) | Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) |

## When to use

You should use Delegated DCV when all of the following conditions are true:

* Your zone is using a [partial DNS setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/).
* Cloudflare is not already [performing DCV automatically](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/).
* Your zone is using an [Advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/).
* The Certificate Authority is either Google Trust Services, SSL.com, or Let's Encrypt

### Aspects to keep in mind

As explained in the [announcement blog post ↗](https://blog.cloudflare.com/introducing-dcv-delegation/), currently, you can only delegate DCV to one provider at a time. This means:

* If you also issue publicly trusted certificates for the same hostname for your [origin server](https://developers.cloudflare.com/ssl/concepts/#origin-certificate), this will no longer be possible. You can use [Cloudflare origin CA certificates](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/) instead.
* If your zone is using multiple CDN providers, you might want to use an alternative [method](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/). This is because, once the DCV delegation is configured for Cloudflare, only Cloudflare will be able to perform DCV on your behalf, blocking your external CDN providers from doing the same.

## Setup

To set up Delegated DCV:

1. Order an [advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/) for your zone, choosing `TXT` as the **Certificate validation method**.
2. On the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page, go to **DCV Delegation for Partial Zones**.
3. Copy the Cloudflare validation URL.
4. At your authoritative DNS provider, create `CNAME` record(s) considering the following:
* If your certificate only covers the apex domain and a wildcard, you only need to create a single `CNAME` record for your apex domain. Any direct subdomains will be covered as well.

```

_acme-challenge.example.com CNAME example.com.<COPIED_VALIDATION_URL>.


```

* If your certificate also covers subdomains specified by their name, you will need to add multiple `CNAME` records to your authoritative DNS provider, one for each specific subdomain.

For example, a certificate covering `example.com`, `*.example.com`, and `sub.example.com` would require the following records.

```

_acme-challenge.example.com CNAME example.com.<COPIED_VALIDATION_URL>.

_acme-challenge.sub.example.com CNAME sub.example.com.<COPIED_VALIDATION_URL>.


```

Remove previous TXT records

Existing TXT records for `_acme-challenge` will conflict with the delegated DCV CNAME record. Make sure to check and remove records such as the following:

```

_acme-challenge.example.com TXT <CERTIFICATE_VALIDATION_VALUE>


```

Once the `CNAME` records are in place, Cloudflare will add TXT DCV tokens for every hostname on the Advanced certificate that has a DCV delegation record in place, as long as the zone is [active](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/) on Cloudflare.

Because DCV happens regularly, do not remove the `CNAME` record(s) at your authoritative DNS provider. Otherwise, Cloudflare will not be able to perform DCV on your behalf and your certificate will not be issued.

## Further details

### Testing

If you use a `dig` command to test, you should only be able see the placed tokens if the certificate is up for issuance.

This is because Cloudflare places the tokens when needed and then cleans them up.

Terminal window

```

dig TXT +noadditional +noquestion +nocomments +nocmd +nostats _acme-challenge.example.com. @1.1.1.1


_acme-challenge.example.com. 3600    IN    CNAME    example.com.<COPIED_VALIDATION_URL>


```

### Renewal

If a hostname becomes unreachable during certificate renewal time, the certificate will not be able to be renewed automatically via Delegated DCV. Should you need to renew a certificate for a hostname that is not resolving currently, you can send a PATCH request to [the changing DCV method API endpoint](https://developers.cloudflare.com/api/resources/ssl/subresources/verification/methods/edit/) and change the method to TXT to proceed with manual renewal per [the TXT DCV method](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/txt/).

Once the hostname becomes resolvable again, [Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/) will resume working as expected.

### Moved domains

If you [move your zone to another account](https://developers.cloudflare.com/fundamentals/manage-domains/move-domain/), you will need to update the `CNAME` record at your authoritative DNS provider with a new validation URL.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/","name":"Domain control validation (DCV)"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/methods/","name":"Methods"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/","name":"Delegated"}}]}
```

---

---
title: HTTP
description: Validate domain control with an HTTP token on your origin.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# HTTP

When you choose HTTP DCV, Cloudflare automatically adds a verification HTTP token to your domain.

Only use this method if your domain can tolerate a few minutes of downtime.

Note

If you encounter issues with HTTP DCV, refer to the [troubleshooting guide](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/troubleshooting/).

## Limitations

HTTP DCV is only available for [proxied domains](https://developers.cloudflare.com/dns/proxy-status/). It is possible to manually add the DCV token to the `.well-known/pki-validation/` directory on your origin web server to pre-validate your certificates.

HTTP DCV validation does not work for wildcard certificates. If you want to use wildcard certificates, use [TXT validation](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/txt/).

Based on your chosen certificate authority (CA), you may also not be able to use HTTP verification with [advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/).

## Setup

### Specify DCV method

If you want to use a [Universal SSL certificate](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/enable-universal-ssl/), you will need to edit the `validation_method` [via the API](https://developers.cloudflare.com/api/resources/ssl/subresources/verification/methods/edit/) and specify your chosen validation method.

Alternatively, you could [order an advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/#create-a-certificate) via the API.

In either case, you would need to set a `"validation_method":"http"` parameter.

### Review other Cloudflare settings

To make sure your domain does not accidentally block HTTP DCV, review your Cloudflare settings for [common setup issues](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/troubleshooting/).

### Complete DCV

Your HTTP token will be available for the certificate authority as soon as you finish your [partial domain setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/setup/#3-add-dns-records).

This means that you need to add a CNAME record to Cloudflare in your authoritative DNS and create [proxied DNS records](https://developers.cloudflare.com/dns/proxy-status/) for your hostname within Cloudflare.

This process may involve a few minutes of downtime.

What happens after you create your records

Cloudflare contacts one of our certificate authority (CA) providers and asks them to issue certificates for the specified hostname. The CA will then inform Cloudflare that we need to demonstrate control of this hostname by returning a `$DCV_TOKEN` at a specified `$DCV_FILENAME`; both the token and the filename are randomly generated by the CA and not known to Cloudflare ahead of time.

For example, if you create a new custom hostname for `site.example.com`, the CA might ask us to return the value `ca3-38734555d85e4421beb4a3e6d1645fe6` for a request to `http://site.example.com/.well-known/pki-validation/ca3-39f423f095be4983922ca0365308612d.txt"`. As soon as we receive that value from the CA we make it accessible at our edge and ask the CA to confirm it is there so that they can complete validation and the certificate order.

To check whether your certificates have been validated and reissued:

* **Dashboard**: Find the certificate(s) on the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page and make sure that the **Status** is **Active**.
* **API**: Send a [GET](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/list/) request and confirm that your certificate(s) have `"status": "active"`.

## Renewal

Even if you manually handle DCV when issuing certificates in a [partial DNS setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/), at certificate renewal, Cloudflare will attempt to automatically perform DCV via HTTP.

If all of the following conditions are confirmed at the first attempt, the renewal happens automatically via [HTTP](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/http/).

* Hostnames are proxied.
* Hostnames on the certificate resolve to the IPs assigned to the zone.
* The certificate does not contain wildcards.

Note

To automatically renew certificates that do not meet the referred criteria, consider using [Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/).

If the conditions are met but HTTP DCV fails successively, the process will fall back to TXT. This schedule varies according to the certificate validity period.

* 90-days certificates: after failing for 15 days
* 30-days certificates: after failing for 7 days
* 14-days certificates: after failing for 3 days

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/","name":"Domain control validation (DCV)"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/methods/","name":"Methods"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/methods/http/","name":"HTTP"}}]}
```

---

---
title: TXT
description: Validate domain control with a TXT DNS record.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# TXT

TXT record validation requires the creation of a TXT record in the hostname's authoritative DNS.

  
---

## When to use

Generally, you need to perform TXT-based DCV when your certificate [requires DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/) and you cannot perform [Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/).

---

## Setup

### Specify DCV method

If you want to use a [Universal SSL certificate](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/enable-universal-ssl/), you will need to edit the `validation_method` [via the API](https://developers.cloudflare.com/api/resources/ssl/subresources/verification/methods/edit/) and specify your chosen validation method.

Alternatively, you could [order an advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) via the dashboard or the API.

### Get DCV values

Once you [create a new certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/#create-a-certificate) and choose the validation method of **TXT**, your tokens will be ready after a few seconds.

These tokens can be fetched through the API or the dashboard when the certificates are in a [pending validation](https://developers.cloudflare.com/ssl/reference/certificate-statuses/#new-certificates) state during custom hostname creation or during certificate renewals.

* [ API ](#tab-panel-10455)
* [ Dashboard ](#tab-panel-10456)

You can access these tokens using the API with the [GET request](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/get/) and including `status=pending_validation` as a request parameter.

For example, here are two tokens highlighted in the API response for a wildcard certificate.

Response

```

{

  "result": [

    {

      "id": "<CERTIFICATE_ID>",

      "type": "advanced",

      "hosts": ["*.<DOMAIN>.com", "<DOMAIN>.com"],

      "primary_certificate": "0",

      "status": "pending_validation",

      "certificates": [],

      "created_on": "2022-10-12T21:46:21.979150Z",

      "validity_days": 90,

      "validation_method": "txt",

      "validation_records": [

        {

          "status": "pending",

          "txt_name": "_acme-challenge.<DOMAIN>.com",

          "txt_value": "lXLOcN6cPv0nproViNcUHcahD9TrIPlNgdwesj0pYpk"

        },

        {

          "status": "pending",

          "txt_name": "_acme-challenge.<DOMAIN>.com",

          "txt_value": "O0o8VgJu_OGu-T30_cvT-4xO5ZX1_2WsVNUrpUKE6ns"

        }

      ],

      "certificate_authority": "google"

    }

  ]

}


```

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. Select a certificate.
3. Copy the values for **Certificate validation TXT name** and **Certificate validation TXT value**.

If you had created a **wildcard** certificate, you would need to copy the values for two different validation TXT records.

### Update DNS records

At your authoritative DNS provider, create a TXT record named the `txt_name` and containing the `txt_value`.

Repeat this process for all the DCV records returned in the `validation_records` field to your Authoritative DNS provider.

If one or more of the hostnames on the certificate fail to validate, the certificate will not be issued or renewed.

This means that a wildcard certificate covering `example.com` and `*.example.com` will require two DCV tokens to be placed at the authoritative DNS provider. Similarly, a certificate with five hostnames in the SAN (including a wildcard) will require five DCV tokens to be placed at the authoritative DNS provider. Certificates with several packs (RSA and ECDSA for example) may also require several DCV tokens.

### Complete DCV

Once you update your DNS records, you can either [wait for the next retry](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/validation-backoff-schedule/) or request an immediate recheck.

To request an immediate recheck, send another [PATCH request](https://developers.cloudflare.com/api/resources/ssl/subresources/verification/methods/edit/) with the same `validation_method` as your current validation method.

TXT records used for DCV can be removed from your authoritative DNS provider as soon as the certificate is issued.

## Renewal

Even if you manually handle DCV when issuing certificates in a [partial DNS setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/), at certificate renewal, Cloudflare will attempt to automatically perform DCV via HTTP.

If all of the following conditions are confirmed at the first attempt, the renewal happens automatically via [HTTP](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/http/).

* Hostnames are proxied.
* Hostnames on the certificate resolve to the IPs assigned to the zone.
* The certificate does not contain wildcards.

Note

To automatically renew certificates that do not meet the referred criteria, consider using [Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/).

If any one of the conditions is not met, the certificate renewal falls back to your chosen method and you will need to [repeat the DCV process](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/txt/#get-dcv-values) manually.

Cloudflare generates renewal tokens 30 days before certificate expiration.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/","name":"Domain control validation (DCV)"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/methods/","name":"Methods"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/methods/txt/","name":"TXT"}}]}
```

---

---
title: Troubleshooting
description: Resolve domain control validation failures.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

If your certificate is stuck in **Pending Validation** or failing to issue, the certificate authority (CA) may be unable to complete [domain control validation (DCV)](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/dcv-flow/). This page helps you identify and resolve common DCV issues.

Note

If you are using the Cloudflare API, error messages are presented under the `validation_errors` parameter.

## Quick checklist

Use this checklist to identify common DCV issues:

* [No rules blocking the validation URL](#blocked-validation-url) \- WAF rules, IP access rules, or Under Attack mode can block the CA
* [No redirects on the validation path](#redirection) \- The `/.well-known/*` path must not redirect (especially HTTP to HTTPS in partial setups)
* [DNS records are resolvable](#dns-settings-and-records) \- DNSSEC must be valid, and records must resolve from all locations
* [CAA records allow the CA](#caa-records) \- CAA records must permit Cloudflare's partner CAs to issue certificates
* [No CA-side errors](#ca-errors) \- Rate limits, policy blocks, or temporary CA issues

---

## Blocked validation URL

If you have issues while HTTP DCV is in place, review the following settings:

* **Anything affecting `/.well-known/*`**: Review [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/), [IP Access Rules](https://developers.cloudflare.com/waf/tools/ip-access-rules/), and other [configuration rules](https://developers.cloudflare.com/rules/configuration-rules/) to make sure that your rules _do not_ enable interactive challenge on the validation URL.
* **Cloudflare Account Settings** and **Page Rules**: Review your [account settings](https://developers.cloudflare.com/fundamentals/reference/under-attack-mode/), [Configuration Rules](https://developers.cloudflare.com/rules/configuration-rules/), and [Page Rules](https://developers.cloudflare.com/rules/page-rules/) to ensure you have not enabled Under Attack mode on the validation URL.  
Warning  
When your certificate is in `pending_validation` and valid tokens are in place, some security features targeting your zone's path for `/.well-known/*` can be automatically bypassed.

## Redirection

Enabling [Always Use HTTPS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/) does not impact the validation process.

In a [Partial (CNAME) setup](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/#partial-dns-setup---action-sometimes-required) where you are managing the token on the origin side, please ensure that no redirection from HTTP to HTTPS occurs on the `/.well-known/*` path.

When using [Redirect Rules](https://developers.cloudflare.com/rules/url-forwarding/single-redirects/), exclude the `/.well-known/*` path from redirections by adding a condition to your rule:

```

not starts_with(http.request.uri.path, "/.well-known/")


```

For example, if you have a rule that redirects all HTTP traffic to HTTPS, modify the rule expression to:

```

(http.request.scheme eq "http") and not starts_with(http.request.uri.path, "/.well-known/")


```

## DNS settings and records

The errors below refer to situations that have to be addressed at the authoritative DNS provider:

* `the Certificate Authority had trouble performing a DNS lookup: dns problem: looking up caa for <hostname>: dnssec: bogus`
* `Certificate authority encountered a SERVFAIL during DNS lookup, please check your DNS reachability.`

Consider the following when troubleshooting:

* [DNSSEC ↗](https://www.cloudflare.com/learning/dns/dns-security/) must be configured correctly. You can use [DNSViz ↗](https://dnsviz.net/) to understand and troubleshoot the deployment of DNSSEC.
* The HTTP verification process is done preferably over **IPv6**, so if any AAAA record exists and does not point to the same dual-stack location as the A record, the validation will fail.
* If an [NS record](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#ns) is present for the hostname or its parent, DNS resolution will be managed externally by the DNS provider defined in the NS target. In this case, you must either add the DCV TXT record at the external DNS provider, or remove the NS record at Cloudflare.

### CAA records

* Your [CAA records](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/) must be resolvable from all locations.
* Your [CAA records](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/) should allow Cloudflare's partner [certificate authorities (CAs)](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) to issue certificates on your behalf.
* If you are using a [subdomain setup](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/) (`subdomain.example.com`) and Cloudflare is not the authoritative DNS provider for the parent domain (`example.com`), you should make sure that the parent domain (`example.com`) either has CAA records that allow [Cloudflare's partner CAs](https://developers.cloudflare.com/ssl/reference/certificate-authorities/), or has no CAA records at all.

You can check the CAA records by running the following command:

* [ macOS and Linux ](#tab-panel-10457)
* [ Windows ](#tab-panel-10458)

Terminal window

```

dig example.com CAA +short


```

PowerShell

```

Resolve-DnsName -Name example.com -Type CAA


```

## Certificate authority (CA) errors

A [certificate authority (CA)](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) is the organization that issues your SSL/TLS certificate. Cloudflare partners with multiple CAs to provide certificates for your domain.

Note

Selecting a different CA is only available with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) or [SSL for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/). [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) customers cannot change the CA.

### Rate limiting

As mentioned in [Certificate authorities](https://developers.cloudflare.com/ssl/reference/certificate-authorities/), specific CAs may have their own limitations. If you use Let’s Encrypt and receive the error below, it means you hit the [duplicate certificate limit ↗](https://letsencrypt.org/docs/duplicate-certificate-limit/) imposed by Let's Encrypt.

`The authority has rate limited these domains. Please wait for the rate limit to expire or try another authority.`

A certificate is considered a duplicate of an earlier certificate if it contains the exact same set of hostnames.

In this case, you can either wait for the rate limit window to end or choose a different certificate authority.

When you see `The authority has rate limited these domains. Please wait for the rate limit to expire or try another authority`, the certificate authority has temporarily blocked certificate issuance for your domain due to too many recent requests.

Rate limit windows vary by CA:

* **Let's Encrypt**: 7 days for most rate limits (refer to [Let's Encrypt rate limits ↗](https://letsencrypt.org/docs/rate-limits/))
* **Google Trust Services**: Varies by limit type (refer to [Google Trust Services documentation ↗](https://pki.goog/faq/))

**Resolution**: Wait for the rate limit window to expire, or select a different CA.

### CAA records block issuance

The error `CAA records block issuance. Please remove all CAA records or add records for this authority` indicates that your domain's [CAA records](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/) do not allow the selected certificate authority to issue certificates.

**Resolution**: Either remove all CAA records from your domain, or add CAA records that explicitly allow [Cloudflare's partner certificate authorities](https://developers.cloudflare.com/ssl/reference/certificate-authorities/).

### Multiple perspective validation errors

Certificate authorities perform domain validation from multiple geographic locations to prevent certain attacks. You may encounter one of these errors:

* `Certificate authority encountered a multiple perspective CAA check error, please ensure your DNS is configured to allow CAA queries from all geographic perspectives`
* `Certificate authority was unable to verify domain ownership from multiple geographic locations (MPIC failure). Please ensure your DNS records are reachable from all geographic perspectives and try again.`

**Resolution**: Ensure your DNS records (including CAA records) are consistently resolvable from all geographic locations. You can investigate resolution errors using the [ping.pe tool ↗](https://dig.ping.pe/). For example, for a [Google Trust Services](https://developers.cloudflare.com/ssl/reference/certificate-authorities/#google-trust-services) certificate, check: `<hostname>:CAA:8.8.8.8`.

Read more from certificate authority documentation: [SSL.com ↗](https://www.ssl.com/blogs/multi-perspective-issuance-corroboration-mpic-arrives/), [Let's Encrypt ↗](https://letsencrypt.org/2020/02/19/multi-perspective-validation), and [Google Trust Services ↗](https://pki.goog/faq/#faq-mpic).

### DNS lookup errors

The error `the Certificate Authority had trouble performing a DNS lookup` indicates that the CA could not resolve your domain's DNS records. Common causes include SERVFAIL responses, NXDOMAIN, or DNSSEC validation failures.

**Resolution**: Verify that your DNS records are correctly configured and resolvable. Use tools like [DNSViz ↗](https://dnsviz.net/) to check for DNSSEC issues, and ensure your authoritative nameservers are responding correctly.

### Rejected identifier

The error `The certificate authority will not issue for this domain. Please check your input or try another authority` means the CA has policies that prevent issuing certificates for your specific domain.

**Resolution**: Verify that your domain name is correctly spelled and does not violate the CA's issuance policies. If the domain is valid, try selecting a different CA.

### Internal errors

When you see `Internal error with Certificate Authority. Please check later`, the certificate authority encountered a temporary issue during validation.

**Resolution**: Wait a few minutes and retry. If the issue persists, try selecting a different CA. Cloudflare will automatically retry validation according to the [validation backoff schedule](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/validation-backoff-schedule/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/","name":"Domain control validation (DCV)"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: Validation backoff schedule
description: Consider what happens if a domain control validation (DCV) fails and what schedule Cloudflare follows for new attempts and backoff.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Validation backoff schedule

Domain control validation (DCV) has to happen before a certificate authority (CA) will issue a certificate for a domain. If DCV fails during issuance or renewal, Cloudflare automatically retries it on a schedule.

If you use [Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/) or if [Cloudflare automatically performs DCV for you](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/), this page is only informational. If you have to manually perform DCV, consider the following sections about the validation schedule and remember that DCV tokens have a [fixed validity period](#dcv-tokens-validity).

Note

You can also request an immediate recheck by using the [Edit SSL Certificate Pack Validation Method endpoint](https://developers.cloudflare.com/api/resources/ssl/subresources/verification/methods/edit/), specifying the same `validation_method` as the [method](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/) you currently use.

---

## DCV tokens validity

The DCV process relies on tokens that are generated by the issuing certificate authority. These tokens have a validity period defined by each CA:

* Google Trust Services - 14 days
* Let's Encrypt - 7 days
* SSL.com - 14 days

After this period, DCV tokens expire as dictated by the [CA/B Baseline Requirements ↗](https://cabforum.org/baseline-requirements-documents/), and new, valid tokens must be placed.

Warning

Tokens may also become invalid upon validation failure. For more details, refer to [Domain control validation flow](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/dcv-flow/#dcv-tokens).

---

## Successive checks function

Cloudflare caps the check backoff to a maximum of four hours to avoid the function growing exponentially, which would result in large gaps between checks towards the end of the month.

```

now() + min((floor(60 * pow(1.05, retry_attempt)) * INTERVAL '1 second'), INTERVAL '4 hours')


```

---

## Capped attempts reference table

As presented in the following table, most of the checks take place on the first day after the DCV token is generated.

In manual processes, it is possible that you fall behind schedule when you place the token, meaning that it may not be validated immediately.

In automatic processes, most validations complete within the first five minutes, unless there is a setup misconfiguration.

| Retry Attempt | In Seconds | In Minutes | In Hours |
| ------------- | ---------- | ---------- | -------- |
| 0             | 60         | 1.000      | 0.016667 |
| 1             | 63         | 1.050      | 0.017500 |
| 2             | 66         | 1.100      | 0.018333 |
| 3             | 69         | 1.150      | 0.019167 |
| 4             | 72         | 1.200      | 0.020000 |
| 5             | 76         | 1.267      | 0.021111 |
| 6             | 80         | 1.333      | 0.022222 |
| 7             | 84         | 1.400      | 0.023333 |
| 8             | 88         | 1.467      | 0.024444 |
| 9             | 93         | 1.550      | 0.025833 |
| 10            | 242        | 4.033      | 0.067222 |
| 11            | 279        | 4.650      | 0.077500 |
| 12            | 321        | 5.350      | 0.089167 |
| 13            | 369        | 6.150      | 0.102500 |
| 14            | 424        | 7.067      | 0.117778 |
| 15            | 488        | 8.133      | 0.135556 |
| 16            | 561        | 9.350      | 0.155833 |
| 17            | 645        | 10.750     | 0.179167 |
| 18            | 742        | 12.367     | 0.206111 |
| 19            | 853        | 14.217     | 0.236944 |
| 20            | 981        | 16.350     | 0.272500 |
| 21            | 1129       | 18.817     | 0.313611 |
| 22            | 1298       | 21.633     | 0.360556 |
| 23            | 1493       | 24.883     | 0.414722 |
| 24            | 1717       | 28.617     | 0.476944 |
| 25            | 1975       | 32.917     | 0.548611 |
| 26            | 2271       | 37.850     | 0.630833 |
| 27            | 2612       | 43.533     | 0.725556 |
| 28            | 3003       | 50.050     | 0.834167 |
| 29            | 3454       | 57.567     | 0.959444 |
| 30            | 3972       | 66.200     | 1.103333 |
| 31            | 4568       | 76.133     | 1.268889 |
| 32            | 5253       | 87.550     | 1.459167 |
| 33            | 6041       | 100.683    | 1.678056 |
| 34            | 6948       | 115.800    | 1.930000 |
| 35            | 7990       | 133.167    | 2.219444 |
| 36            | 9189       | 153.150    | 2.552500 |
| 37            | 10567      | 176.117    | 2.935278 |
| 38            | 12152      | 202.533    | 3.375556 |
| 39            | 13975      | 232.917    | 3.881944 |
| 40            | 14400      | 240.000    | 4.000000 |
| 41            | 14400      | 240.000    | 4.000000 |
| 42            | 14400      | 240.000    | 4.000000 |
| 43            | 14400      | 240.000    | 4.000000 |
| 44            | 14400      | 240.000    | 4.000000 |
| 45            | 14400      | 240.000    | 4.000000 |
| 46            | 14400      | 240.000    | 4.000000 |
| 47            | 14400      | 240.000    | 4.000000 |
| 48            | 14400      | 240.000    | 4.000000 |
| 49            | 14400      | 240.000    | 4.000000 |
| 50            | 14400      | 240.000    | 4.000000 |
| 51            | 14400      | 240.000    | 4.000000 |
| 52            | 14400      | 240.000    | 4.000000 |
| 53            | 14400      | 240.000    | 4.000000 |
| 54            | 14400      | 240.000    | 4.000000 |
| 55            | 14400      | 240.000    | 4.000000 |
| 56            | 14400      | 240.000    | 4.000000 |
| 57            | 14400      | 240.000    | 4.000000 |
| 58            | 14400      | 240.000    | 4.000000 |
| 59            | 14400      | 240.000    | 4.000000 |
| 60            | 14400      | 240.000    | 4.000000 |
| 61            | 14400      | 240.000    | 4.000000 |
| 62            | 14400      | 240.000    | 4.000000 |
| 63            | 14400      | 240.000    | 4.000000 |
| 64            | 14400      | 240.000    | 4.000000 |
| 65            | 14400      | 240.000    | 4.000000 |
| 66            | 14400      | 240.000    | 4.000000 |
| 67            | 14400      | 240.000    | 4.000000 |
| 68            | 14400      | 240.000    | 4.000000 |
| 69            | 14400      | 240.000    | 4.000000 |
| 70            | 14400      | 240.000    | 4.000000 |
| 71            | 14400      | 240.000    | 4.000000 |
| 72            | 14400      | 240.000    | 4.000000 |
| 73            | 14400      | 240.000    | 4.000000 |
| 74            | 14400      | 240.000    | 4.000000 |
| 75            | 14400      | 240.000    | 4.000000 |
| 76            | 14400      | 240.000    | 4.000000 |
| 77            | 14400      | 240.000    | 4.000000 |
| 78            | 14400      | 240.000    | 4.000000 |
| 79            | 14400      | 240.000    | 4.000000 |
| 80            | 14400      | 240.000    | 4.000000 |
| 81            | 14400      | 240.000    | 4.000000 |
| 82            | 14400      | 240.000    | 4.000000 |
| 83            | 14400      | 240.000    | 4.000000 |
| 84            | 14400      | 240.000    | 4.000000 |
| 85            | 14400      | 240.000    | 4.000000 |
| 86            | 14400      | 240.000    | 4.000000 |
| 87            | 14400      | 240.000    | 4.000000 |
| 88            | 14400      | 240.000    | 4.000000 |
| 89            | 14400      | 240.000    | 4.000000 |
| 90            | 14400      | 240.000    | 4.000000 |
| 91            | 14400      | 240.000    | 4.000000 |
| 92            | 14400      | 240.000    | 4.000000 |
| 93            | 14400      | 240.000    | 4.000000 |
| 94            | 14400      | 240.000    | 4.000000 |
| 95            | 14400      | 240.000    | 4.000000 |
| 96            | 14400      | 240.000    | 4.000000 |
| 97            | 14400      | 240.000    | 4.000000 |
| 98            | 14400      | 240.000    | 4.000000 |
| 99            | 14400      | 240.000    | 4.000000 |
| 100           | 14400      | 240.000    | 4.000000 |
| 101           | 14400      | 240.000    | 4.000000 |
| 102           | 14400      | 240.000    | 4.000000 |
| 103           | 14400      | 240.000    | 4.000000 |
| 104           | 14400      | 240.000    | 4.000000 |
| 105           | 14400      | 240.000    | 4.000000 |
| 106           | 14400      | 240.000    | 4.000000 |
| 107           | 14400      | 240.000    | 4.000000 |
| 108           | 14400      | 240.000    | 4.000000 |
| 109           | 14400      | 240.000    | 4.000000 |
| 110           | 14400      | 240.000    | 4.000000 |
| 111           | 14400      | 240.000    | 4.000000 |
| 112           | 14400      | 240.000    | 4.000000 |
| 113           | 14400      | 240.000    | 4.000000 |
| 114           | 14400      | 240.000    | 4.000000 |
| 115           | 14400      | 240.000    | 4.000000 |
| 116           | 14400      | 240.000    | 4.000000 |
| 117           | 14400      | 240.000    | 4.000000 |
| 118           | 14400      | 240.000    | 4.000000 |
| 119           | 14400      | 240.000    | 4.000000 |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/","name":"Domain control validation (DCV)"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/validation-backoff-schedule/","name":"Validation backoff schedule"}}]}
```

---

---
title: Custom certificates
description: Upload and manage your own TLS certificates on Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Custom certificates

Custom certificates are meant for Business and Enterprise customers who want to use their own SSL certificates.

  
Use custom certificates when you need control over the certificate authority (CA) or require Organization Validated (OV) or Extended Validation (EV) certificates that Cloudflare-managed options do not support.

Unlike [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) or [advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/), Cloudflare does not manage issuance and renewal for custom certificates. You are responsible for the following:

* [Upload the certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/#upload-a-custom-certificate).
* [Update the certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/#update-an-existing-custom-certificate) before it expires.
* [Monitor the certificate expiration date](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/renewing/) to avoid downtime.

Note

If your custom certificate does not cover all of your first-level hostnames, you can enable [Universal SSL certificate](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) to cover them.

If your custom certificate is from a [certificate authority that Cloudflare partners with](https://developers.cloudflare.com/ssl/reference/certificate-authorities/), consider switching to a Cloudflare-managed certificate to benefit from automatic issuance and renewal.

## Certificate packs

Before deploying custom certificates to Cloudflare's global network, Cloudflare automatically groups the certificates into certificate packs.

A certificate pack is a group of certificates that share the same set of hostnames — for example, `example.com` and `*.example.com` — but use different signature algorithms.

Each pack can include up to three certificates, one from each of the following signature algorithms:

* `SHA-2/RSA`
* `SHA-2/ECDSA`
* `SHA-1/RSA`

Each pack only counts as one SSL certificate against your custom certificate quota.

Note

You cannot delete the primary certificate if secondary certificates are present in the pack.

## Availability

| Free                  | Pro | Business | Enterprise            |                                                               |
| --------------------- | --- | -------- | --------------------- | ------------------------------------------------------------- |
| Availability          | No  | No       | Yes                   | Yes                                                           |
| Certificates included | 0   | 0        | 1 Modern and 1 Legacy | 1 Modern (can purchase more) and 1 Legacy (can purchase more) |

## Related features

### Certificate Signing Requests (CSRs)

You can use Cloudflare to generate a [Certificate Signing Request (CSR)](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/certificate-signing-requests/) for your custom certificate. When you do, Cloudflare generates and securely stores the private key associated with the CSR.

### Geo Key Manager (private key restriction)

By default, Cloudflare encrypts and securely distributes private keys to all Cloudflare data centers, where they can be used for local SSL/TLS termination. If you want to restrict where your private keys may be used, use [Geo Key Manager](https://developers.cloudflare.com/ssl/edge-certificates/geokey-manager/).

### Keyless SSL

If you want to upload a custom certificate but retain your private key on your own infrastructure, consider using [Keyless SSL](https://developers.cloudflare.com/ssl/keyless-ssl/).

### Certificate pinning

Custom certificates are the only certificate type where certificate pinning can work on Cloudflare. For guidance on pinning and its risks, refer to [Certificate pinning](https://developers.cloudflare.com/ssl/reference/certificate-pinning/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/custom-certificates/","name":"Custom certificates"}}]}
```

---

---
title: Bundle methodologies
description: Certificate chain bundling options for custom certificates.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Bundle methodologies

When an SSL certificate is deployed to Cloudflare's global network, it may be augmented with intermediate and root certificates to assist the user agent in finding a chain to a publicly trusted root.

You can control the mechanics of how certificates are bundled by specifying a bundling methodology.

## Intermediate and root certificates

Cloudflare maintains intermediate and root certificates used for bundling on a [GitHub repository ↗](https://github.com/cloudflare/cfssl%5Ftrust). As the certificates expire or are removed by certificate authorities, Cloudflare removes and adds them accordingly.

Expiration values for these certificates may appear in the `expires_on` field when you use the [Analyze Certificate endpoint](https://developers.cloudflare.com/api/resources/ssl/subresources/analyze/methods/create/) \- often when the methodology you specify is [Compatible](#compatible). However, these expiration values reflect intermediate and root certificates - which are handled by Cloudflare -, not the leaf certificate you would have previously uploaded to Cloudflare.

Note

When using `compatible` or `modern`, a selection might be done on the intermediates you provide at upload time, meaning it is not guaranteed all of them will make it to the final chain. If you must ensure the chain you upload is the one used, select `user-defined`.

## Methodologies

### Compatible

Compatible is the default methodology and uses common and well distributed intermediate certificates to complete the chain. This ensures that the resulting bundle is compatible with as many clients as possible.

The related value for the `bundle_method` parameter when using the [API](https://developers.cloudflare.com/api/resources/custom%5Fcertificates/methods/create/) is `ubiquitous`.

### Modern

Modern consists of attempts to make the chain as efficient as possible, often by using newer or fewer intermediate certificates.

The related value for the `bundle_method` parameter when using the [API](https://developers.cloudflare.com/api/resources/custom%5Fcertificates/methods/create/) is `optimal`.

### User-defined

User-defined allows you to paste your own certificate chain and present that bundle to clients. If you are using a self-signed certificate (not recommended), you must use this mode.

The related value for the `bundle_method` parameter when using the [API](https://developers.cloudflare.com/api/resources/custom%5Fcertificates/methods/create/) is `force`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/custom-certificates/","name":"Custom certificates"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/custom-certificates/bundling-methodologies/","name":"Bundle methodologies"}}]}
```

---

---
title: Remove key file password
description: Remove the password from a private key file before uploading.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Remove key file password

You cannot upload a custom certificate with a password-protected key file.

The process for removing the password depends on your operating system. The following examples remove the password from `example.com.key`.

Linux

1. Open a command console.
2. Go to the directory containing the `example.com.key` file.
3. Copy the original key.  
Terminal window  
```  
cp example.com.key temp.key  
```
4. Run the following command (if using an ECDSA certificate, replace `rsa` with `ec`).  
Terminal window  
```  
openssl rsa -in temp.key -out example.com.key  
```
5. When prompted in the console window, enter the original key password.
6. [Upload the file contents](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/#upload-a-custom-certificate) to Cloudflare.

Windows

1. Go to [https://indy.fulgan.com/SSL/ ↗](https://indy.fulgan.com/SSL/) and download the latest version of OpenSSL for your x86 or x86\_64 operating system.
2. Open the `.zip` file and extract it.
3. Select **openssl.exe**.
4. In the command window that appears, run:  
Terminal window  
```  
rsa -in C:\Path\To\example.com.key -out key.pem  
```
5. Enter the original key password when prompted by the **openssl.exe** command window.
6. [Upload](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/#upload-a-custom-certificate) the contents of the `key.pem` file to Cloudflare.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/custom-certificates/","name":"Custom certificates"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/custom-certificates/remove-file-key-password/","name":"Remove key file password"}}]}
```

---

---
title: Renewal and expiration
description: Learn how renewal and expiration work when using Cloudflare Custom SSL certificates.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Renewal and expiration

## Renew custom certificates

Since Cloudflare cannot renew uploaded certificates, you should ensure that you replace or [update](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/#update-an-existing-custom-certificate) an expiring custom certificate before it expires, otherwise your visitors may not be able to connect.

Cloudflare automatically sends email notifications 30 and 14 days before your custom certificate expires. The email is sent to users who have the SSL/TLS, Administrator, or Super Administrator [roles](https://developers.cloudflare.com/fundamentals/manage-members/roles/).

Note

When renewing a custom certificate, you can reuse a [previously generated CSR](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/certificate-signing-requests/).

If you are on an Enterprise plan and want to renew a custom (modern) certificate, consider requesting access to [Staging environment (Beta)](https://developers.cloudflare.com/ssl/edge-certificates/staging-environment/).

## Expired certificates

If a valid replacement - covering some or all of the SANs in the expiring custom certificate - is already available, Cloudflare will remove the expiring custom certificate in the 24 hours before expiration. There is no expected downtime due to certificate transition.

If no valid replacement is available, Cloudflare will remove the custom certificate after it expires.

Affected domains and subdomains will fall back to any other active certificate covering the hostnames on the expiring certificate.

Warning

All certificates in a [certificate pack](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/#certificate-packs) are treated as one object. The expiration date of a certificate pack is equivalent to the soonest `Not After` date among the certificates in the pack.

For example if you have a custom certificate made of an ECSDA and a RSA certificate, if one of them expires the whole pack will be removed.

## Migrate to other certificate types

If you no longer want to use your custom certificate but still want your website or application to be covered with SSL/TLS, you can do the following:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. Make sure there is already an active [universal](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) or [advanced](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) certificate covering the same hostnames.
3. Delete your custom certificate.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/custom-certificates/","name":"Custom certificates"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/custom-certificates/renewing/","name":"Renewal and expiration"}}]}
```

---

---
title: Troubleshooting
description: Troubleshoot issues with custom certificates.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

## Generic troubleshooting

### Make sure your key and certificate match

You can use an external tool such as the [SSLShopper Certificate Key Matcher ↗](https://www.sslshopper.com/certificate-key-matcher.html) to check your certificate and make sure the key matches.

Alternatively, use `openssl` to verify the match by comparing the public key hash of both files. This method works for both RSA and ECDSA certificates:

Terminal window

```

openssl x509 -noout -pubkey -in certificate.crt | openssl md5

openssl pkey -pubout -in private.key | openssl md5


```

If the two outputs match, the certificate and key are a valid pair.

### Check the certificate details

You can use `openssl` to check all the details of your certificate:

Terminal window

```

openssl x509 -in certificate.crt -noout -text


```

Then, make sure all the information is correct before uploading.

### Remove password from private key

Cloudflare does not accept password-protected private keys. If your private key requires a password, remove it before uploading. The following command works for both RSA and ECDSA keys:

Terminal window

```

openssl pkey -in protected.key -out unprotected.key


```

Use the `unprotected.key` file when uploading to Cloudflare. For detailed instructions, refer to [Remove key file password](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/remove-file-key-password/).

### Private key format requirements

Private keys must be in one of the following unencrypted formats:

* PKCS#8
* PKCS#1
* Elliptic Curve

## Moved domains

If you move a domain without deleting the custom certificate from the previous zone, the certificate may still [take precedence](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/) and be presented to your visitors, until the previous zone is [deleted](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/).

Refer to [Move a domain between Cloudflare accounts](https://developers.cloudflare.com/fundamentals/manage-domains/move-domain/#issue-new-certificates) for details.

## Let's Encrypt chain update

As Let's Encrypt - one of the [certificate authorities (CAs)](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) used by Cloudflare - has announced changes in its [chain of trust](https://developers.cloudflare.com/ssl/concepts/#chain-of-trust), you may face issues.

If you are using a Let's Encrypt certificate uploaded by yourself as a custom certificate, consider the following:

* If you use **compatible** or **modern** [bundle method](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/bundling-methodologies/) and have uploaded your certificate before September 9, 2024, [update your custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/#update-an-existing-custom-certificate) so that it can be bundled with the new chain.
* If you use **user-defined** bundle method, make sure that your certificates uploaded after September 30, 2024, do not use the Let's Encrypt cross-signed chain.

## Error codes

### Invalid certificate. (Code: 1002)

**Root cause**

The certificate you are trying to upload is invalid. For example, there might be extra lines, or the BEGIN/END text is not correct, or extra characters are added following a copy/paste.

In the case of an update with the [PATCH API call](https://developers.cloudflare.com/api/resources/custom%5Fcertificates/methods/edit/), it can mean the path parameter `{custom_certificate_id}` is invalid.

**Solution**

Carefully check the content of the certificate. You may use `openssl` to check all the details of your certificate:

Terminal window

```

openssl x509 -in certificate.crt -noout -text


```

When using the API, carefully check the `{custom_certificate_id}` path parameter. You can confirm the certificate ID by [listing the existing custom certificates](https://developers.cloudflare.com/api/resources/custom%5Fcertificates/methods/list/) (`id` in the response).

### You have reached the maximum number of custom certificates. (Code: 1212)

**Root cause**

You have used up your custom certificate quota.

**Solution**

Delete some existing certificates to add a new one. If you are an Enterprise customer, you can contact your account team to acquire more custom certificates.

### This certificate has already been submitted. (Code: 1220)

**Root cause**

You are trying to upload a custom certificate that you have already uploaded.

**Solution**

Delete the existing one and try again.

### You already have a certificate of this signature type. (Code: 1228)

**Root cause**

A custom certificate pack can only have one certificate per signature algorithm (for example, one RSA and one ECDSA certificate).

**Solution**

Instead of uploading a new certificate, update the existing certificate using the edit option in the dashboard or the [PATCH API endpoint](https://developers.cloudflare.com/api/resources/custom%5Fcertificates/methods/edit/).

### This certificate cannot be deleted at this time. (Code: 1305)

**Root cause**

This error occurs when there is an issue with the certificate pack structure. You must delete other certificates in the pack before deleting this one.

**Solution**

Delete the other certificates in the certificate pack first, then delete this certificate. If the issue persists, [contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/).

### Only root CA certificate is allowed. (Code: 1411)

**Root cause**

You are trying to upload a certificate to the [custom origin trust store](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/#custom-origin-trust-store), but the certificate is not a valid root CA certificate.

**Solution**

When creating a self-signed root CA certificate, ensure you use the `-extensions v3_ca` option with OpenSSL. Refer to [this community post ↗](https://community.cloudflare.com/t/only-root-ca-certificate-is-allowed-code-1411/505318) for more details.

### The SSL attribute is invalid. Please refer to the API documentation, check your input and try again. (Code: 1434)

**Root cause**

You are trying to upload a custom certificate that does not support any cipher that is needed by Chromium-based browsers.

**Solution**

Modify the certificate so that it supports chromium-supported ciphers and try again.

### You have reached your quota for the requested resource. (Code: 2005)

**Root cause**

The quota for custom certificates depends on the **type** of certificate (**Custom Legacy** vs **Custom Modern**).

If you try to upload a certificate **type** but have already reached your quota, you will receive this error.

**Solution**

First, check your custom certificate entitlements on the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page.

Then, when actually uploading or editing the certificate, make sure you select the appropriate option for **Legacy Client Support**.

### The certificate chain you uploaded cannot be bundled using Cloudflare's trust store. Please check your input and try again. (Code: 2100)

**Root cause**

You are trying to upload a custom certificate that contains the root and leaf certificate at the same time.

**Solution**

Upload the leaf certificate only.

### The certificate chain you uploaded has no leaf certificates. Please check your input and try again. (Code: 2101)

**Root cause**

You are trying to upload a root + intermediate + intermediate `.crt` file, but the actual leaf certificate is in a separate file.

**Solution**

Add the leaf to the `.crt` file, or just use the leaf by itself since the Certificate Authority has a public chain of trust in our trust store.

### The certificate chain you uploaded does not include any hostnames from your zone. Please check your input and try again. (Code: 2103)

**Root cause**

Cloudflare verifies that uploaded custom certificates include a hostname for the associated zone. Moreover, this hostname must be included as a Subject Alternative Name (SAN). This is following the standard set by the [CA/Browser Forum ↗](https://cabforum.org/wp-content/uploads/BRv1.2.5.pdf#page=16).

**Solution**

Make sure your certificate contains a Subject Alternative Name (SAN) specifying a hostname in your zone. You can use the `openssl` command below and look for `Subject Alternative Name` in the output.

Terminal window

```

openssl x509 -in certificateFile.pem -noout -text


```

If it does not exist, you will need to request a new certificate.

### The private key you uploaded is invalid. Please check your input and try again. (Code: 2106)

**Root cause**

Cloudflare requires separate, pem-encoded files for the SSL private key and certificate.

**Solution**

Contact your Certificate Authority (CA) to confirm whether your current certificate meets this requirement or request your CA to assist with certificate format conversion.

Make sure your certificate complies with these [requirements](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/#certificate-requirements).

Check that the certificate and private keys match before uploading the certificate in the Cloudflare dashboard. This [external resource ↗](https://www.sslshopper.com/article-most-common-openssl-commands.html) might help.

### The certificate and private key pair you uploaded is invalid. (Code: 2200)

**Root cause**

The certificate and private key you uploaded do not form a valid pair. The private key does not correspond to the public key in the certificate. This can happen when the wrong key file is selected during upload.

**Solution**

Ensure the private key corresponds to the certificate you are uploading. You can verify this by comparing the public key hash of both files. This method works for both RSA and ECDSA certificates:

Terminal window

```

openssl x509 -noout -pubkey -in certificate.crt | openssl md5

openssl pkey -pubout -in private.key | openssl md5


```

If the outputs do not match, you have mismatched the certificate and key.

### An unknown error has occurred. (Code: 2000)

**Root cause**

An internal error occurred while processing your request.

**Solution**

Wait a few minutes and try again. If the issue persists, [contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) with a [HAR file](https://developers.cloudflare.com/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/#generate-a-har-file) capturing the failed upload attempt.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/custom-certificates/","name":"Custom certificates"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/custom-certificates/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: Manage custom certificates
description: Upload, update, and delete custom certificates.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Manage custom certificates

This page lists Cloudflare requirements for custom certificates and explains how to upload and update these certificates using Cloudflare dashboard or API.

## Certificate requirements

Before accepting custom certificates, Cloudflare parses them and checks for validity according to a list of requirements.

Full list of requirements

Each custom certificate you upload must:

* Be encoded in PEM format (PEM, PKCS#7, or PKCS#12). See [Converting Using OpenSSL ↗](https://www.sslshopper.com/article-most-common-openssl-commands.html) for conversion examples.
* Not have a [key file password](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/remove-file-key-password/).
* Not be expiring in less than 14 days from time of upload.
* Have a subject alternative name (SAN) matching at least one hostname in the zone where it is being uploaded.
* Use a private key greater than or equal to a minimum length. Currently, 2048 bit for RSA and 225 bit for ECDSA.
* Be publicly trusted by a major browser. This does not apply for certificates that specify `User Defined` as their [bundling methodology](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/bundling-methodologies/).
* Be one of the following certificate types:  
   * Unified Communications Certificates (UCC)  
   * Extended Validation (EV)  
   * Domain Validated (DV)  
   * Organization Validated (OV)

---

## Upload a custom certificate

Warning

When using `compatible` or `modern` [bundling](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/bundling-methodologies), make sure to upload only the leaf certificate. This will allow Cloudflare to properly handle [the expiration of intermediate and root certificates](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/bundling-methodologies/#intermediate-and-root-certificates).

* [ Dashboard ](#tab-panel-10461)
* [ API ](#tab-panel-10462)

To upload a custom SSL certificate in the dashboard:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. In **Edge Certificates**, select **Upload Custom SSL Certificate**.
3. Copy and paste relevant values into **SSL Certificate** and **Private key** text areas (or select **Paste from file**).  
Note  
If doing this manually, include the `---BEGIN CERTIFICATE---` and `---END CERTIFICATE---` like the placeholder text.
4. Choose the appropriate [**Bundle Method**](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/bundling-methodologies/).
5. Select a value for [**Private Key Restriction**](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/#geo-key-manager-private-key-restriction).
6. Select a value for **Legacy Client Support**, which specifies [Server Name Indication (SNI)](https://developers.cloudflare.com/ssl/reference/browser-compatibility/#non-sni-support) support:  
   * **Modern (recommended)**: SNI only  
   * **Legacy**: Supports non-SNI  
   Warning  
   Custom certificates of the type `legacy_custom` are not compatible with [BYOIP](https://developers.cloudflare.com/byoip/).
7. Select **Upload Custom Certificate**. If you see an error for `The key you provided does not match the certificate`, contact your Certificate Authority to ensure the private key matches the certificate.
8. (optional) [Add a CAA DNS record](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/).

The following call will upload a certificate for use with `app.example.com`. Cloudflare will automatically bundle the certificate with a certificate chain optimized for maximum compatibility with browsers.

Warning

Note that if you are using an ECC key generated by OpenSSL, you will need to first remove the `-----BEGIN EC PARAMETERS-----...-----END EC PARAMETERS-----` section of the file.

1. Update the file and build the payload

Terminal window

```

cat app_example_com.pem


```

```

-----BEGIN CERTIFICATE-----

MIIFJDCCBAygAwIBAgIQD0ifmj/Yi5NP/2gdUySbfzANBgkqhkiG9w0BAQsFADBN

MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E

...

SzSHfXp5lnu/3V08I72q1QNzOCgY1XeL4GKVcj4or6cT6tX6oJH7ePPmfrBfqI/O

OeH8gMJ+FuwtXYEPa4hBf38M5eU5xWG7

-----END CERTIFICATE-----


```

Terminal window

```

MYCERT="$(cat app_example_com.pem|perl -pe 's/\r?\n/\\n/'|sed -e 's/..$//')"

MYKEY="$(cat app_example_com.key|perl -pe 's/\r?\n/\\n/'|sed -e's/..$//')"


```

With the certificate and key saved to environment variables (using escaped newlines), build the payload:

Terminal window

```

request_body=$(< <(cat <<EOF

{

  "certificate": "$MYCERT",

  "private_key": "$MYKEY",

  "bundle_method": "ubiquitous"

}

EOF

))


```

You can optionally add [geographic restrictions ↗](https://blog.cloudflare.com/introducing-cloudflare-geo-key-manager/) that specify where your private key can physically be decrypted:

Terminal window

```

request_body=$(< <(cat <<EOF

{

  "certificate": "$MYCERT",

  "private_key": "$MYKEY",

  "bundle_method": "ubiquitous",

  "geo_restrictions": {"label": "us"}'

}

EOF

))


```

You can also enable support for legacy clients which do not include SNI in the TLS handshake.

Terminal window

```

request_body=$(< <(cat <<EOF

{

  "certificate": "$MYCERT",

  "private_key": "$MYKEY",

  "bundle_method": "ubiquitous",

  "geo_restrictions": {"label": "us"}',

  "type":"sni_custom"

}

EOF

))


```

`sni_custom` is recommended by Cloudflare. Use `legacy_custom` when a specific client requires non-SNI support. The Cloudflare API treats all Custom SSL certificates as Legacy by default.

Warning

Custom certificates of the type `legacy_custom` are not compatible with [BYOIP](https://developers.cloudflare.com/byoip/).

1. Upload your certificate and key

Use the [POST](https://developers.cloudflare.com/api/resources/custom%5Fcertificates/methods/create/) endpoint to upload your certificate and key.

Terminal window

```

curl https://api.cloudflare.com/client/v4/zones/{zone_id}/custom_certificates \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data "$request_body"


```

1. (Optional) Add a CAA record.

A Certificate Authority Authorization (CAA) DNS record specifies which certificate authorities (CAs) are allowed to issue certificates for a domain. This record reduces the chance of unauthorized certificate issuance and promotes standardization across your organization.

For more guidance, refer to [Create a CAA record](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/).

---

## Update an existing custom certificate

Before you update an existing custom certificate, you might want to consider having active [universal](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) or [advanced](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) certificates as fallback options. Go to the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page to check a list of hostnames and status of the edge certificates in your zone.

If you are on an Enterprise plan and want to update a custom (modern) certificate, also consider requesting access to [Staging environment (Beta)](https://developers.cloudflare.com/ssl/edge-certificates/staging-environment/).

Replacing a custom certificate following these steps does not lead to any downtime. No connections will be terminated and new connections will use the new certificate. The old certificate will only actually be deleted when the new certificate is uploaded and active.

* [ Dashboard ](#tab-panel-10459)
* [ API ](#tab-panel-10460)

To update a certificate in the dashboard:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. In **Edge Certificates**, locate a custom certificate and select it to expand.
3. Select the wrench button and choose **Replace SSL certificate and key**.
4. Follow the same steps as [upload a new certificate](#upload-a-custom-certificate).

To update a certificate using the API, send a [PATCH](https://developers.cloudflare.com/api/resources/custom%5Fcertificates/methods/edit/) command.

Note

To update the **Private Key Restriction** setting of a certificate, delete and re-add the certificate.

---

## Delete a custom certificate

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. In **Edge Certificates**, locate a custom certificate and select it to expand.
3. Select the cross button.
4. Select **Confirm** to delete the certificate.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/custom-certificates/","name":"Custom certificates"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/custom-certificates/uploading/","name":"Manage custom certificates"}}]}
```

---

---
title: ECH Protocol
description: Encrypt the SNI field with Encrypted Client Hello for improved privacy.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# ECH Protocol

ECH stands for [Encrypted Client Hello ↗](https://datatracker.ietf.org/doc/draft-ietf-tls-esni/16/). It is a protocol extension in the context of Transport Layer Security (TLS). ECH encrypts part of the handshake and masks the Server Name Indication (SNI) that is used to negotiate a TLS session. This means that whenever a user visits a website on Cloudflare that has ECH enabled, intermediaries will be able to see that you are visiting a website on Cloudflare, but they will not be able to determine which one.

## What ECH does

ECH limits access to information that a particular user is visiting your website, ensuring that it is not unnecessarily shared with intermediaries, like Internet Service Providers (ISP). With ECH, specific details regarding their visit no longer leak to network intermediaries when the user accesses your website.

## How ECH works

In a typical [TLS handshake ↗](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/), the client sends a ClientHello message to the server to initiate the TLS session. This message contains important information, including the list of supported cryptographic algorithms, TLS version, and the requested server name (the domain name of the website the client wants to connect to). The server name is indicated through Server Name Indication (SNI).

With ECH, the ClientHello message part is split into two separate messages: an inner part and an outer part. The outer part contains the non-sensitive information such as which ciphers to use and the TLS version and an "outer ClientHello". The inner part is encrypted and contains an "inner ClientHello".

The outer ClientHello contains a common name (SNI) that represents that a user is trying to visit an encrypted website on Cloudflare. We chose `cloudflare-ech.com` as the SNI that all websites will share on Cloudflare. Because Cloudflare controls that domain, we have the appropriate certificates to be able to negotiate a TLS handshake for that server name.

The inner ClientHello contains the actual server name that the user is trying to visit. This is encrypted using a public key and can only be read by Cloudflare. Once the handshake completes, the web page is loaded as normal, just like any other website loaded over TLS.

In practice, this means that any intermediary that is looking at your traffic will simply see normal TLS handshakes with one caveat: any traffic to an ECH-enabled server name on Cloudflare will look the same. Every TLS handshake will appear identical in that it looks like it is trying to load a website for `cloudflare-ech.com`, as opposed to the actual website.

In the example below, a user is visiting `example.com`. Without ECH, any intermediate networks will be able to detect the website being accessed by the user. With ECH, the visible information will be limited to `cloudflare-ech.com` instead.

  
flowchart LR
accTitle: What intermediaries see with and without ECH
accDescr: This diagram describes what intermediaries see with and without ECH.
A(User visits <code>example.com</code>)
    A -- With ECH --> C(intermediaries see <code>cloudflare-ech.com</code>)-->B(Cloudflare)
    A -- Without ECH  --> D(intermediaries see <code>example.com</code>)-->B(Cloudflare)

  
For more details about ECH protocol technology, refer to our [introductory blog ↗](https://blog.cloudflare.com/encrypted-client-hello/).

## Enable ECH

ECH is enabled by default on Free zones. Other plans can turn it on or off following the steps below.

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. For **Encrypted ClientHello (ECH)**, change the setting to **Enabled**.

## Enterprise network applicability

Some enterprise or regional networks may need to audit or apply filtering policies to traffic that traverses their network. These policies are expressed in terms of domain names, not IP addresses. Consequently, they are best applied at the local DNS resolver in response to the `A` and `AAAA` queries for the individual domain names.

However, for settings wherein DNS-based filtering is not applicable, there are two ways in which networks can disable ECH to allow existing filtering mechanisms to continue working as expected.

The most reliable way is via the local or recursive DNS resolver itself, by dropping ECH configurations from HTTPS resource records returned to clients, or, preferably, by returning a “no error no answer” or NXDOMAIN response to HTTPS queries. This prevents clients from obtaining the necessary information to use ECH. Note that modifying HTTPS resource records may cause failures for clients that perform DNSSEC validation, so dropping HTTPS responses may be the preferred approach. This will prevent browsers, such as Chrome from using ECH.

The second way to disable ECH is via a network canary domain. In particular, your network’s DNS resolver can return a “no error no answer” or an NXDOMAIN response to queries made to the `use-application-dns.net` [canary domain ↗](https://support.mozilla.org/en-US/kb/canary-domain-use-application-dnsnet). This will prevent browsers, such as Firefox from using ECH. For more information, see Firefox's [frequently asked questions page ↗](https://support.mozilla.org/en-US/kb/faq-encrypted-client-hello#w%5Fhow-will-ech-interact-with-dohs-opt-outs) for Encrypted Client Hello.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/ech/","name":"ECH Protocol"}}]}
```

---

---
title: Enforce HTTPS connections
description: Force all visitor traffic to use HTTPS connections.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Enforce HTTPS connections

Even with an active SSL/TLS certificate, visitors can still access resources over unsecured HTTP connections.

It is best to redirect this traffic over HTTPS, as well as ensure other resources (such as images) are also loaded over HTTPS.

## Prerequisites

Before trying to enforce HTTPS connections, make sure that your application has an active [edge certificate](https://developers.cloudflare.com/ssl/get-started/#choose-an-edge-certificate). Otherwise, visitors will not be able to access your application at all.

Also, make sure that your [SSL encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/) is not set to **Off**. Otherwise, Cloudflare will redirect all visitor connections automatically to HTTP.

## 1\. Evaluate existing redirects

To make sure that your visitors do not get stuck in a [redirect loop](https://developers.cloudflare.com/ssl/troubleshooting/too-many-redirects/), evaluate existing redirects at your origin server and within the Cloudflare dashboard.

You should generally avoid redirects at your origin server. Not only are you likely to forget about them, but they also reduce application performance. It is much faster for Cloudflare to redirect requests before they ever reach your origin.

Make sure that your redirects within Cloudflare are not forwarding traffic to URLs starting with `http`.

## 2\. Rewrite HTTP URLs

If your application contains links or references to HTTP URLs, your visitors might see [mixed content errors](https://developers.cloudflare.com/ssl/troubleshooting/mixed-content-errors/) when accessing an HTTPS page.

To avoid these issues, enable [Automatic HTTPS Rewrites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/automatic-https-rewrites/) and pay attention to which HTTP requests are still reaching your origin server.

## 3\. Redirect traffic to HTTPS

If your entire application can support HTTPS traffic, enable [Always Use HTTPS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/#encrypt-all-visitor-traffic).

If only some parts of your application can support HTTPS traffic, do not enable **Always Use HTTPS** and use a [single redirect](https://developers.cloudflare.com/rules/url-forwarding/single-redirects/) to selectively perform the redirect to HTTPS. Refer to [Redirect admin area requests to HTTPS](https://developers.cloudflare.com/rules/url-forwarding/examples/redirect-admin-https/) for an example.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/encrypt-visitor-traffic/","name":"Enforce HTTPS connections"}}]}
```

---

---
title: Geo Key Manager
description: Control the geographic storage location of your private SSL/TLS keys.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Geo Key Manager

Restrict where the private keys used for TLS certificates are stored and managed.

Geo Key Manager allows customers to store and manage the encryption keys for their domains in different geographic locations so they can meet compliance regulations and keep data secure.

## Resources

* [ Setup ](https://developers.cloudflare.com/ssl/edge-certificates/geokey-manager/setup/)
* [ Supported options ](https://developers.cloudflare.com/ssl/edge-certificates/geokey-manager/supported-options/)

## Limitations

Currently, Geo Key Manager is limited to [custom certificates](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) and available only through the Cloudflare API.

---

## Related products

**[Data Localization Suite](https://developers.cloudflare.com/data-localization/)** 

The Data Localization Suite (DLS) is a set of products that helps customers who want to maintain local control over their traffic while retaining the security benefits of a global network.

**[Geo Key Manager (v1)](https://blog.cloudflare.com/introducing-cloudflare-geo-key-manager/)** 

The first version of Geo Key Manager supports 3 regions: U.S., E.U., and a set of High Security Data Centers. If you would like to restrict your private key to another country or region, [apply for the closed beta ↗](https://www.cloudflare.com/lp/geo-key-manager/) of the new version.

---

## More resources

[Plans](https://www.cloudflare.com/plans/#overview) 

Compare available Cloudflare plans

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/geokey-manager/","name":"Geo Key Manager"}}]}
```

---

---
title: Setup
description: Learn how to set up Geo Key Manager and choose the geographical boundaries of where your private encryption keys are stored.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Setup

## Geo Key Manager v2 Beta

Note

Geo Key Manager v2 is only available through the Cloudflare API.

Geo Key Manager v2 gives customers flexibility when choosing the geographical boundaries of where their keys are stored.

Using the `policy` field, customers can define policies containing allow and block lists of countries or regions where the private key should be stored.

To use Geo Key Manager v2 with the API, generally, follow the steps to [upload a custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/#upload-a-custom-certificate).

When sending the [POST](https://developers.cloudflare.com/api/resources/custom%5Fcertificates/methods/create/) request, include the `policy` parameter to define policies containing allow and block lists of countries or regions where the private key should be stored.

Note

You also have access to the `geo_restrictions` parameter, which is mutually exclusive with the `policy` parameter and is part of [Geo Key Manager v1](#geo-key-manager-v1).

### Examples

Store private keys in the E.U. and the U.S.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Access: Mutual TLS Certificates Write`
* `SSL and Certificates Write`

Create SSL Configuration

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_certificates" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "certificate": "certificate",

    "private_key": "<PRIVATE_KEY>",

    "policy": "(country: US) and (region: EU)",

    "type": "sni_custom"

  }'


```

Store private keys in the E.U., but not in France

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Access: Mutual TLS Certificates Write`
* `SSL and Certificates Write`

Create SSL Configuration

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_certificates" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "certificate": "certificate",

    "private_key": "<PRIVATE_KEY>",

    "policy": "(region: EU) and (not country: FR)",

    "type": "sni_custom"

  }'


```

Note

For more information on the `policy` field, refer to [Supported options](https://developers.cloudflare.com/ssl/edge-certificates/geokey-manager/supported-options/).

## Geo Key Manager v1

The first version of Geo Key Manager supports 3 regions: U.S., E.U., and a set of High Security Data Centers. If you would like to restrict your private key to another country or region, [apply for the closed beta ↗](https://www.cloudflare.com/lp/geo-key-manager/) of the new version.

* [ Dashboard ](#tab-panel-10463)
* [ API ](#tab-panel-10464)

To use Geo Key Manager in the dashboard:

1. Follow the steps to [upload a custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/#upload-a-custom-certificate).
2. For **Private Key Restriction**, choose one of the following options:  
   * **Distribute to all Cloudflare data centers (optimal performance)**  
   * **Distribute only to U.S. data centers**  
   * **Distribute only to E.U. data centers**  
   * **Distribute only to highest security data centers** ([more details](https://developers.cloudflare.com/ssl/edge-certificates/geokey-manager/supported-options/#highest-security-data-centers))
3. Select **Upload Custom Certificate**.

To use Geo Key Manager with the API, generally, follow the steps to [upload a custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/#upload-a-custom-certificate).

When sending the [POST](https://developers.cloudflare.com/api/resources/custom%5Fcertificates/methods/create/) request, include the `geo_restrictions` parameter set to one of the following options:

* `us`
* `eu`
* `highest_security`([more details](https://developers.cloudflare.com/ssl/edge-certificates/geokey-manager/supported-options/#highest-security-data-centers))

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/geokey-manager/","name":"Geo Key Manager"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/geokey-manager/setup/","name":"Setup"}}]}
```

---

---
title: Supported options
description: Learn which options are supported for Geo Key Manager.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Supported options

## Available regions

For customers with Geo Key Manager v2, you can use the `policy` parameter to specify following regions using the **Region code**:

| Region code | Region name           |
| ----------- | --------------------- |
| AFR         | Africa                |
| APAC        | Asia Pacific          |
| EEUR        | Eastern Europe        |
| ENAM        | Eastern North America |
| EU          | European Union        |
| ME          | Middle East           |
| OC          | Oceania               |
| SAM         | South America         |
| WEUR        | Western Europe        |
| WNAM        | Western North America |

---

## Available countries

For customers with Geo Key Manager v2, you can use the `policy` parameter to specify individual countries as well. Cloudflare is constantly expanding the number of supported countries. To indicate a country, specify the two-letter (ISO 3166) country code.

Examples of supported countries are Japan, Canada, India, and Australia.

---

## Highest security data centers

For customers with both Geo Key Manager v1 and v2, you can use the `geo_restrictions` parameter to only choose Cloudflare's highest security data centers.

The following aspects are unique to our highest security data centers, but the baseline security requirements for all data centers are also detailed in [our blog ↗](https://blog.cloudflare.com/introducing-cloudflare-geo-key-manager/).

### Pre-scheduled and biometric controlled facility access

Employees of Cloudflare permitted to access the facility must have previously scheduled a visit before access will be granted.

Access to the entrance of the facility is controlled through the use of a biometric hand reader combined with an assigned access code.

### Private cages with biometric readers

All equipment is in private cages with physical access controlled via biometrics and recorded in audit logs. Entrants have to pass through five separate readers before they can access the cage.

### Exterior security controls and monitoring

All points of ingress/egress are monitored by an intrusion detection system (IDS), with authorized users and access events archived for historical review.

### Interior security controls and monitoring

Interior points of ingress/egress are controlled by the access control subsystem, with entry routed through a mantrap. All areas are monitored and recorded with closed-circuit television, with data kept for a minimum of thirty days.

Exterior walls are airtight and may incorporate additional security measures such as reinforced concrete, Kevlar bullet board, vapor barriers, or bullet-proof front doors.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/geokey-manager/","name":"Geo Key Manager"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/geokey-manager/supported-options/","name":"Supported options"}}]}
```

---

---
title: Staging environment
description: Test certificate changes in a staging environment before production.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Staging environment

Use your certificate staging environment to test new custom (modern) certificates before pushing them to your production environment. This process helps you solve potential certificate problems **before** there's an incident, such as when:

* You make a mistake when uploading a new custom certificate.
* You misunderstand the order of your certificates.
* Clients have previously pinned your custom certificate, causing a TLS termination error.

## Availability

| Free         | Pro | Business | Enterprise |                 |
| ------------ | --- | -------- | ---------- | --------------- |
| Availability | No  | No       | No         | Yes (open beta) |

---

## Use your staging environment

### 1\. Upload certificate

To upload custom (modern) certificates to your staging environment:

1. In the Cloudflare dashboard, go to the **Staging Certificates** page.  
[ Go to **Staging Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/staging-certificates)
2. Select **Upload Custom Staging Certificate**.
3. Upload your custom (modern) certificate ([detailed instructions](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/)).
4. Your certificate will appear in the dashboard with a status of **Staging Deployment**. If you refresh the page, its status should go to **Staging Active**.

### 2\. Test certificate

Test your custom (modern) certificate by sending `curl` requests to the IP addresses listed on the [**Staging Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/staging-certificates) page:

```

curl --resolve <HOSTNAME>:<PORT>:<STAGING_IP> https://<HOSTNAME> -iv


```

You should confirm whether:

* TLS termination is successful.
* The right certificate is being served at the edge.
* Any clients are pinning the old certificate.

### 3\. Push certificate to production

Assuming there are no issues, push your custom (modern) certificate to your production environment:

1. In the Cloudflare dashboard, go to the **Staging Certificates** page.  
[ Go to **Staging Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/staging-certificates)
2. Select a custom certificate.
3. Select **Push to Production**.

If there were issues with your certificate, you can keep it in your staging environment or select **Deactivate** on the certificate itself.

### 4\. (Optional) Push certificate back to staging

If you roll out a custom (modern) certificate to production and encounter issues, you can deactivate that certificate to delete the certificate from the edge and then push the certificate back to your staging environment for additional testing:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. Select a custom certificate.
3. Select **Deactivate**.
4. Select **Push to Staging**.

---

## Limitations

### Access

Currently, staging environments are only available to Enterprise customers participating in an open beta. To get access to the beta, contact your Account team.

### Functionality

At the moment, staging environments have limited functionality:

* Only custom (modern) certificates
* Only accessed via the dashboard

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/staging-environment/","name":"Staging environment"}}]}
```

---

---
title: Universal SSL
description: Free TLS certificates automatically issued for all proxied hostnames.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Universal SSL

By default, Cloudflare issues — and [renews](https://developers.cloudflare.com/ssl/reference/certificate-validity-periods/#universal-ssl) — free, unshared, publicly trusted SSL certificates to all domains [added to](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) and [activated on](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/) Cloudflare.

On a [full setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/), Universal SSL certificates cover your root domain (for example, `example.com`) and first-level subdomains (for example, `www.example.com`). On a [partial (CNAME) setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/), each proxied subdomain receives its own certificate regardless of depth. Cloudflare handles issuance, renewal, and deployment automatically.

For full setup zones that need coverage beyond first-level subdomains, use [Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/) or [advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/).

Universal certificates are [Domain Validated (DV)](https://developers.cloudflare.com/ssl/concepts/#validation-level), which means the certificate authority verifies domain ownership but does not validate organization identity. For setup details, refer to [Enable Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/enable-universal-ssl/).

Note

Universal SSL certificates are issued after your domain is active on Cloudflare. If you need an SSL certificate before migrating traffic, or if you need to [customize cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/), use [Advanced](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) or [Custom](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) certificates.

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

## Related resources

* [Limitations](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/limitations/)
* [Backup certificates](https://developers.cloudflare.com/ssl/edge-certificates/backup-certificates/)
* [Validity period and renewal](https://developers.cloudflare.com/ssl/reference/certificate-validity-periods/#universal-ssl)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/universal-ssl/","name":"Universal SSL"}}]}
```

---

---
title: Alerts
description: Notifications for Universal SSL certificate events.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Alerts

You can configure alerts to receive notifications for changes in your certificates.

Universal SSL Alert

**Who is it for?**

Customers with universal certificates who want to receive a notification on validation, issuance, renewal, and expiration notices.

**Other options / filters**

None.

**Included with**

All Cloudflare plans.

**What should you do if you receive one?**

You only need to take action if you are notified that you have a certificate that failed. You can find the reasons why a certificate is not being issued in [Troubleshooting SSL errors](https://developers.cloudflare.com/ssl/troubleshooting/general-ssl-errors/).

Refer to [Cloudflare Notifications](https://developers.cloudflare.com/notifications/get-started/) for more information on how to set up an alert.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/universal-ssl/","name":"Universal SSL"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/universal-ssl/alerts/","name":"Alerts"}}]}
```

---

---
title: Disable Universal SSL certificates
description: Turn off Universal SSL certificates for your domain.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Disable Universal SSL certificates

Some customers may need to manage their own SSL certificates or rely on specific Certificate Authorities.

If you disable your domain's Universal SSL certificate, Cloudflare removes that certificate from our network and will not order or renew any additional Universal SSL certificates.

Disabling Universal SSL will not cause any interruption to ongoing TLS connections to your domain on Cloudflare's network, they will continue to be served according the the Universal SSL certificate used when they were first established. Eventually these connections will naturally end.

New TLS connections are expected to succeed as long as you have another valid certificate active, such as a [custom](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/)) or [advanced](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) certificate. New TLS connections will receive the highest priority certificate from our edge as per our [certificate and hostname priority](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/). If a valid certificate is not active before disabling, TLS connections will fail. For more information, refer to [Potential errors](#potential-errors) below.

## Potential errors

To avoid errors with your domain, either [upload a custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) or purchase [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) before disabling Universal SSL.

If you disable Universal SSL, you may experience errors with the following scenarios:

* **Enabled features**:  
   * [HTTP Strict Transport Security (HSTS)](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/http-strict-transport-security/)  
   * [Always Use HTTPS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/)  
   * [Opportunistic Encryption](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/opportunistic-encryption/)
* **Other setups**:  
   * [Page Rules](https://developers.cloudflare.com/rules/page-rules/) that redirect traffic to HTTPS  
   * HTTP to HTTPS redirects at your origin web server

## Disable Universal SSL certificate

Before you disable Universal SSL/TLS, make sure you have [uploaded a custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) or purchased [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) to protect your domain.

* [ Dashboard ](#tab-panel-10465)
* [ API ](#tab-panel-10466)

To disable Universal SSL in the dashboard:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. For **Disable Universal SSL**, select **Disable Universal SSL**.
3. Read the warnings in the **Acknowledgement**.
4. Select **I Understand** and select **Confirm**.

To disable Universal SSL with the Cloudflare API, send a [PATCH](https://developers.cloudflare.com/api/resources/ssl/subresources/universal/subresources/settings/methods/edit/) request and include the `"enabled": false` parameter.

## Re-enable Universal SSL

* [ Dashboard ](#tab-panel-10467)
* [ API ](#tab-panel-10468)

To re-enable Universal SSL in the dashboard:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. For **Disable Universal SSL**, select **Enable Universal SSL**.

To re-enable Universal SSL with the Cloudflare API, send a [PATCH](https://developers.cloudflare.com/api/resources/ssl/subresources/universal/subresources/settings/methods/edit/) request and include the `"enabled": true` parameter.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/universal-ssl/","name":"Universal SSL"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/universal-ssl/disable-universal-ssl/","name":"Disable Universal SSL certificates"}}]}
```

---

---
title: Enable Universal SSL certificates
description: Turn on Universal SSL certificates for your domain.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Enable Universal SSL certificates

By default, Cloudflare issues — and [renews](https://developers.cloudflare.com/ssl/reference/certificate-validity-periods/#universal-ssl) — free, unshared, publicly trusted SSL certificates to all domains [added to](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) and [activated on](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/) Cloudflare.

---

The process for activating a Universal SSL certificate depends on your domain's DNS setup.

## Full DNS setup

For domains on a [primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/)[1](#user-content-fn-1), your domain should **automatically** receive its Universal SSL certificate within **15 minutes to 24 hours** of domain activation[2](#user-content-fn-2).

This certificate will cover your zone apex (`example.com`) and all first-level subdomains (`subdomain.example.com`), and is provisioned even if your records are DNS only. However, the certificate will only be presented if your domain or subdomains are [proxied](https://developers.cloudflare.com/dns/proxy-status/).

## Footnotes

1. The most common Cloudflare setup that involves changing your authoritative nameservers. [↩](#user-content-fnref-1)
2. Provisioning time depends on certain security checks and other requirements mandated by Certificate Authorities (CA). [↩](#user-content-fnref-2)

### Minimize downtime

If your website or application is already live and cannot be uncovered while the Universal certificate is provisioned, consider the following:

* Order an [advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) before proxying traffic to Cloudflare.
* Upload a [custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) prior to migrating and then delete the certificate after your [Universal certificate is active](#verify-your-certificate-is-active).
* Keep DNS records [**unproxied**](https://developers.cloudflare.com/dns/proxy-status/) until your [certificate is active](#verify-your-certificate-is-active).

Note

If your domain is using a **partial setup**, you will need to add [Domain Control Validation (DCV) records](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/) to your authoritative DNS.

## Partial DNS setup

For non-authoritative or [partial domains](https://developers.cloudflare.com/dns/zone-setups/partial-setup/), Universal SSL will be:

* Provisioned once the DNS record is [proxied through Cloudflare](https://developers.cloudflare.com/dns/zone-setups/partial-setup/setup/#3-add-dns-records).
* Validated:  
   * Immediately if you add [Domain Control Validation (DCV)](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/) records to your authoritative DNS.  
   * After a brief period of downtime if you **do not** add DCV records (once your traffic is proxied).

Unless you cover and validate multiple subdomains with an [advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/), you will need to proxy and validate new subdomains as they are added.

---

## Verify your certificate is active

Once you enable Universal SSL, you can review the [activation status](https://developers.cloudflare.com/ssl/reference/certificate-statuses/) on the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page or via the API with a [GET request](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/list/).

---

## Universal SSL renewal

For Universal certificates, Cloudflare controls the validity periods and certificate authorities (CAs), making sure that renewal always occur.

Partial setup and DCV

If you are on a [CNAME setup (partial)](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/enable-universal-ssl/#partial-dns-setup), make sure [Domain control validation (DCV)](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/) is configured correctly. Refer to [Troubleshooting DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/troubleshooting/) for further help.

Universal certificates have a 90-day validity period. The auto renewal period starts 30 days before expiration.

For details, refer to [Validity periods and renewal](https://developers.cloudflare.com/ssl/reference/certificate-validity-periods/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/universal-ssl/","name":"Universal SSL"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/universal-ssl/enable-universal-ssl/","name":"Enable Universal SSL certificates"}}]}
```

---

---
title: Limitations
description: Review the limitations of Universal certificates, such as hostname coverage, certificate authority  choice, and compatibility with other products.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Limitations

Universal SSL certificates present some limitations.

## Proxy status

Cloudflare can only serve an SSL/TLS certificate for a DNS record when you set the record's [proxy status](https://developers.cloudflare.com/dns/proxy-status/) to **Proxied**. If you do not do this, the origin server your record points to will be responsible for supporting SSL/TLS connections.

## Hostname coverage

### Full setup

When you rely only on Universal SSL in a full setup zone, coverage is limited to the root domain (for example, `example.com`) and first-level subdomains (for example, `www.example.com` or `blog.example.com`). Deeper subdomains — such as `dev.www.example.com` or `app3.dev.www.example.com` — are **not** covered and will not serve a valid certificate.

To enable SSL for deeper subdomains, you can:

* Purchase [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) — then turn on [Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/) for automatic certificate coverage of all proxied subdomains, or manually create advanced certificates for specific hostnames.
* Upload a [custom SSL certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) that includes the required subdomains as Subject Alternative Names (SANs).

### CNAME setup

On a [CNAME setup zone](https://developers.cloudflare.com/dns/zone-setups/partial-setup/), each subdomain (regardless of level) has its own Universal SSL certificate and does not require additional features or purchases. As long as the subdomains are proxied to Cloudflare, a universal certificate [will be provisioned](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/enable-universal-ssl/#partial-dns-setup).

## Certificate authority

For Universal SSL certificates, Cloudflare chooses the certificate authority (CA) used for your certificate.

Cloudflare can change the [certificate authority](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) without prior notification, and will not send any notification as the change happens.

If you want to choose the issuing certificate authority, [order an advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/).

## Validity period

For Universal certificates, Cloudflare controls the validity period. Refer to [validity periods and renewal](https://developers.cloudflare.com/ssl/reference/certificate-validity-periods/#universal-ssl) for details.

## TLS settings

[Customizing cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/) is only available with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) or within [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/).

You can set up [minimum TLS version](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/minimum-tls/) at the zone level, but, for per-hostname settings, you must have [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/).

## Delegated DCV

Delegated DCV allows zones with [partial DNS setups](https://developers.cloudflare.com/dns/zone-setups/partial-setup/) to delegate the DCV process to Cloudflare. DCV delegation will not work with Universal SSL certificates and requires the use of an [advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/).

## Spectrum

Universal SSL is not compatible with [Cloudflare Spectrum](https://developers.cloudflare.com/spectrum/). If you are trying to use Spectrum, use either [an advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) or [a custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/).

## Load balancing

Due to internal limitations, Universal SSL certificates do not cover [load balancing hostnames](https://developers.cloudflare.com/load-balancing/load-balancers/dns-records/) by default. This behavior will be corrected in the future.

## Browser support

For more on browser support, see [Browser compatibility](https://developers.cloudflare.com/ssl/reference/browser-compatibility/).

## SSL invalid brand check

Some domains are not eligible for Universal SSL if they contain words that conflict with trademarked domains.

To resolve this issue, you can:

* Purchase an [advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/).
* Upload your own [custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/).

## Certificate pinning

Cloudflare does not support HTTP public key pinning (HPKP) for universal, advanced, or custom hostname certificates. For details and recommended alternatives, refer to [Certificate pinning](https://developers.cloudflare.com/ssl/reference/certificate-pinning/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/universal-ssl/","name":"Universal SSL"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/universal-ssl/limitations/","name":"Limitations"}}]}
```

---

---
title: Troubleshooting
description: Review how to troubleshoot issues such as certificate timeouts when using Cloudflare Universal SSL.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

## Resolve a timed out state

If a certificate issuance times out, Cloudflare tells you where in the chain of issuance the timeout occurred: Initializing, Validation, Issuance, Deployment, or Deletion.

To resolve timeout issues, try one or more of the following options:

* Change the **Proxy status** of related DNS records to **DNS only** (gray-clouded) and wait at least a minute. Then, change the **Proxy status** back to **Proxied** (orange-clouded).
* [Disable Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/disable-universal-ssl/) and wait at least a minute. Then, re-enable Universal SSL.
* Send a PATCH request to the [validation endpoint](https://developers.cloudflare.com/api/resources/ssl/subresources/verification/methods/edit/) using the same [DCV method](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/) (API only). Make sure that the `--data` field is not empty in your request.
* Review your domain control validation (DCV). Changing the DCV method will restart certificate issuance.

## Delete certificates

You can [use the API](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/delete/) to delete certificates that you no longer want listed on the Cloudflare dashboard.

## Other issues

For additional troubleshooting help, refer to [Troubleshooting SSL errors](https://developers.cloudflare.com/ssl/troubleshooting/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/universal-ssl/","name":"Universal SSL"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/universal-ssl/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: Client certificates (mTLS)
description: Use Cloudflare public key infrastructure (PKI) to create client certificates and enforce mutual Transport Layer Security (mTLS) encryption.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Client certificates (mTLS)

Standard TLS verifies the server's identity to the client. Mutual TLS (mTLS) adds a second check: the server also verifies the client's identity using a client certificate. This allows you to restrict access to devices or services that present a valid certificate.

Use Cloudflare's public key infrastructure (PKI) to create client certificates, or [bring your own CA (BYOCA)](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/).

[Mutual TLS (mTLS)](https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/) authentication is a common security practice that uses client certificates to ensure traffic between client and server is bidirectionally secure and trusted. mTLS also allows requests that do not authenticate via an identity provider — such as Internet-of-things (IoT) devices — to demonstrate they can reach a given resource.

mTLS at Cloudflare

This documentation is focused on the SSL/TLS product. For a broader overview, refer to the [mTLS at Cloudflare learning path](https://developers.cloudflare.com/learning-paths/mtls/concepts/).

---

## How it works

When a hostname has [mTLS enabled](https://developers.cloudflare.com/ssl/client-certificates/enable-mtls/), Cloudflare requires connecting clients to present a valid certificate. Client certificates are installed on the devices or services that should be granted access.

Cloudflare validates client certificates against CAs set at the account level. Because validation is account-level, the same certificates work across multiple domains under your account, as long as mTLS is enabled for each hostname (for example, `host.example.com`, `name.example.net`, `secure.anotherdomain.test`).

The account-level CAs can be:

* The Cloudflare-managed CA: This is the default option. Certificates and hostname associations are listed on the **Cloudflare-issued** tab of the [Client Certificates dashboard ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates/).
* [BYOCA](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/) certificates: Available on Enterprise accounts. Certificates and hostname associations are listed on the **BYOCA** tab of the [Client Certificates dashboard ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates/).

Cloudflare then stores the validation result in a field called [cf.tls\_client\_auth.cert\_verified](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fverified/):

* **Success**: `cf.tls_client_auth.cert_verified` is `true`, and you can find client certificate details in [specific mTLS fields](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/?search-term=cf.tls%5Fclient%5Fauth).
* **Failure**: `cf.tls_client_auth.cert_verified` is `false`.

---

## Use cases

mTLS supports several implementation patterns depending on what you are protecting. For a broader overview, refer to the [mTLS learning path](https://developers.cloudflare.com/learning-paths/mtls/concepts/).

* [Application security](https://developers.cloudflare.com/learning-paths/mtls/mtls-app-security/) — restrict access to your web application based on client certificates
* [mTLS for Zero Trust](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/mutual-tls-authentication/) — authenticate users and services through Cloudflare Access
* [mTLS with API Shield](https://developers.cloudflare.com/api-shield/security/mtls/configure/) — validate API clients with certificate-based authentication
* [mTLS Workers binding](https://developers.cloudflare.com/workers/runtime-apis/bindings/mtls/) — present a client certificate when your Worker connects to an external service

Apart from the mTLS Workers binding, any of the above implementations can use your own CA instead of the Cloudflare-managed one. Refer to [Bring your own CA](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/).

### mTLS and Workers

Use the [mTLS Workers binding](https://developers.cloudflare.com/workers/runtime-apis/bindings/mtls/) when you need your worker to present a client certificate to an external service. To authenticate requests from a client to your worker instead, refer to the regular [mTLS for application security](https://developers.cloudflare.com/learning-paths/mtls/mtls-app-security/) implementation.

flowchart LR
        accTitle: mTLS from client to worker versus mTLS from worker to external service
        accDescr: Diagram showing two different implementations that can be considered for mTLS with Cloudflare Workers.
        A[Client] <--App security mTLS--> B((Cloudflare))<--mTLS worker binding--> C[(External service)]

---

## Further resources

* [ Create a client certificate ](https://developers.cloudflare.com/ssl/client-certificates/create-a-client-certificate/)
* [ Enable mTLS ](https://developers.cloudflare.com/ssl/client-certificates/enable-mtls/)
* [ Bring your own CA for mTLS ](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/)
* [ Forward certificate to server ](https://developers.cloudflare.com/ssl/client-certificates/forward-a-client-certificate/)
* [ Label client certificates ](https://developers.cloudflare.com/ssl/client-certificates/label-client-certificate/)
* [ Revoke a client certificate ](https://developers.cloudflare.com/ssl/client-certificates/revoke-client-certificate/)
* [ Configure your mobile app or IoT device ](https://developers.cloudflare.com/ssl/client-certificates/configure-your-mobile-app-or-iot-device/)
* [ Client certificate variables ](https://developers.cloudflare.com/ssl/client-certificates/client-certificate-variables/)
* [ Troubleshooting ](https://developers.cloudflare.com/ssl/client-certificates/troubleshooting/)
* [ mTLS for Zero Trust ](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/mutual-tls-authentication/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/client-certificates/","name":"Client certificates (mTLS)"}}]}
```

---

---
title: Bring your own CA for mTLS
description: Cloudflare mTLS now supports client certificates that have not been issued by Cloudflare CA. Learn how you can bring your own CA and use it with Cloudflare mTLS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Bring your own CA for mTLS

This page explains how you can manage client certificates that have not been issued by Cloudflare CA. For a broader overview, refer to the [mTLS at Cloudflare learning path](https://developers.cloudflare.com/learning-paths/mtls/concepts/).

Bring your own CA (BYOCA) is especially useful if you already have mTLS implemented and [client certificates are already installed](https://developers.cloudflare.com/ssl/client-certificates/#how-it-works) on devices.

## Availability

* This feature is only available on Enterprise accounts.
* Each Enterprise account can upload up to five CAs. This quota does not apply to CAs uploaded through [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/mutual-tls-authentication/).
* The CA certificate quota is shared across [API Shield](https://developers.cloudflare.com/api-shield/security/mtls/configure/), [Workers mTLS](https://developers.cloudflare.com/workers/runtime-apis/bindings/mtls/), and [Cloudflare Gateway](https://developers.cloudflare.com/cloudflare-one/traffic-policies/).
* To increase this quota, contact your account team.

Note

If you exceed the CA certificate quota, the API returns error `1489` with the message "Hit maximum CA cert allocation." Contact your account team to request a quota increase.

## CA certificate requirements

When you upload your CA, Cloudflare validates the certificate according to certain requirements.

* The CA certificate can be from a publicly trusted CA or self-signed.
* In the certificate `Basic Constraints`, the attribute `CA` must be set to `TRUE`.
* The certificate must use one of the signature algorithms listed below:  
Allowed signature algorithms  
`x509.SHA1WithRSA`  
`x509.SHA256WithRSA`  
`x509.SHA384WithRSA`  
`x509.SHA512WithRSA`  
`x509.ECDSAWithSHA1`  
`x509.ECDSAWithSHA256`  
`x509.ECDSAWithSHA384`  
`x509.ECDSAWithSHA512`

Note

Uploading the CA private key is only required if you wish to use [Zero Trust's block page](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/user-side-certificates/custom-certificate/). To upload your own CA with the private key, use the [Upload mTLS certificate](https://developers.cloudflare.com/api/resources/mtls%5Fcertificates/methods/create/) endpoint.

## Set up mTLS with your CA

* [ Dashboard ](#tab-panel-10421)
* [ API ](#tab-panel-10422)

1. In the Cloudflare dashboard, go to the **Client Certificates** page.  
[ Go to **Client Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. Select **Add Certificate**.
3. In the **Certificate Authority** dropdown, select **Bring your own CA**.
4. Upload your CA certificate file (PEM encoded) and enter a name for the CA.
5. Select **Continue**.
6. On the **Associate Hostnames** page, enter the hostname that should use this CA for mTLS validation and select **Add** for each one. You can also skip this step and associate hostnames later.
7. Select **Save** to confirm.

1. Use the [Upload mTLS certificate endpoint](https://developers.cloudflare.com/api/resources/mtls%5Fcertificates/methods/create/) to upload the CA root certificate.
* `ca` boolean required  
   * Set to `true` to indicate that the certificate is a CA certificate.
* `certificates` string required  
   * Insert content from the `.pem` file associated with the CA certificate, formatted as a single string with `\n` replacing the line breaks.
* `name` string optional  
   * Indicate a unique name for your CA certificate.
* `private_key` string optional  
   * Insert content from the `.pem` file associated with the private key for the certificate, formatted as a single string with `\n` replacing the line breaks.
1. Take note of the certificate ID (`id`) that is returned in the API response.
2. Use the [Replace Hostname Associations endpoint](https://developers.cloudflare.com/api/resources/certificate%5Fauthorities/subresources/hostname%5Fassociations/methods/update/) to enable mTLS in each hostname that should use the CA for mTLS validation. Use the following parameters:
* `hostnames` array required  
   * List the hostnames that will be using the CA for client certificate validation.  
   Warning  
   Submitting an empty array will remove all hostname associations.
* `mtls_certificate_id` string required  
   * Indicate the certificate ID obtained from the previous step.  
   Warning  
   If no `mtls_certificate_id` is provided, the action will be performed against the [Cloudflare-managed CA](https://developers.cloudflare.com/ssl/client-certificates/).
1. (Optional) Make a [GET request](#list-ca-hostname-associations) to confirm the CA hostname associations.

After uploading the CA and associating hostnames, create a custom rule to enforce client certificate validation. You can do this [via the dashboard](https://developers.cloudflare.com/learning-paths/mtls/mtls-app-security/#3-validate-the-client-certificate-in-the-waf) or [via API](https://developers.cloudflare.com/waf/custom-rules/create-api/).

```

  "expression": "(http.host in {\"<HOSTNAME_1>\" \"<HOSTNAME_2>\"} and not cf.tls_client_auth.cert_verified)",

  "action": "block"


```

Note

When using [CNAME records](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#cname), enforce mTLS on the specific hostname where it should be checked. It is not enough to have it set on the CNAME target.

### Multiple CAs for one hostname

There can be multiple CAs (Cloudflare-managed or BYOCA) associated with the same hostname. For BYOCA certificates, the most recently deployed certificate will be prioritized.

If you wish to remove the association from the Cloudflare-managed certificate and only use your BYOCA certificate(s):

* [ Dashboard ](#tab-panel-10427)
* [ API ](#tab-panel-10428)

1. In the Cloudflare dashboard, go to the **Client Certificates** page.  
[ Go to **Client Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. On the **Hosts** section under **Cloudflare-issued Client Certificates**, select **Edit**.
3. Select the cross next to the hostname you want to remove.
4. Select **Save** to confirm.

1. [List the hostname associations](https://developers.cloudflare.com/api/resources/certificate%5Fauthorities/subresources/hostname%5Fassociations/methods/get/) **without** the `mtls_certificate_id` parameter.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`
* `SSL and Certificates Read`

List Hostname Associations

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/certificate_authorities/hostname_associations" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

1. Copy the `hostnames` array returned by the API and update it, removing the hostname that should no longer use the Cloudflare-managed CA.
2. Use the [Replace Hostname Associations endpoint](https://developers.cloudflare.com/api/resources/certificate%5Fauthorities/subresources/hostname%5Fassociations/methods/update/) **without** the `mtls_certificate_id` parameter to perform the action against the Cloudflare-managed CA. For `hostnames` use the list from the previous step.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`

Replace Hostname Associations

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/certificate_authorities/hostname_associations" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "hostnames": [

        "<UPDATED_HOSTNAME_ASSOCIATIONS>"

    ]

  }'


```

## Delete an uploaded CA

If you want to remove a CA that you have previously uploaded, you must first remove any hostname associations that it has.

* [ Dashboard ](#tab-panel-10423)
* [ API ](#tab-panel-10424)

1. In the Cloudflare dashboard, go to the **Client Certificates** page.  
[ Go to **Client Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. Select the **BYOCA** tab.
3. Find the CA you want to delete and select the three dots next to it.
4. Remove all associated hostnames first, if any exist.
5. Select the delete option and confirm.

1. Make a request to the [Replace Hostname Associations endpoint](https://developers.cloudflare.com/api/resources/certificate%5Fauthorities/subresources/hostname%5Fassociations/methods/update/), with an empty array for `hostnames` and specifying your CA certificate ID in `mtls_certificate_id`:

```

  "hostnames": [],

  "mtls_certificate_id": "<CERTIFICATE_ID>"


```

1. Use the [Delete mTLS certificate endpoint](https://developers.cloudflare.com/api/resources/mtls%5Fcertificates/methods/delete/) to delete the certificate.

## List CA hostname associations

* [ Dashboard ](#tab-panel-10425)
* [ API ](#tab-panel-10426)

1. In the Cloudflare dashboard, go to the **Client Certificates** page.  
[ Go to **Client Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. Select the **BYOCA** tab.
3. Find the CA you want to inspect and select the three dots next to it.
4. Select **Edit hostnames**. The **Certificate Details** panel displays the associated hostnames.

Use the [List Hostname Associations endpoint](https://developers.cloudflare.com/api/resources/certificate%5Fauthorities/subresources/hostname%5Fassociations/methods/get/) with the `mtls_certificate_id` query parameter set to the certificate ID of the uploaded CA.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`
* `SSL and Certificates Read`

List Hostname Associations

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/certificate_authorities/hostname_associations?mtls_certificate_id=ID_FROM_STEP_2" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/client-certificates/","name":"Client certificates (mTLS)"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/client-certificates/byo-ca/","name":"Bring your own CA for mTLS"}}]}
```

---

---
title: Client certificate variables
description: Variables available in WAF rules when using client certificates.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Client certificate variables

When a request includes a client certificate for [mTLS authentication](https://developers.cloudflare.com/ssl/client-certificates/enable-mtls/), Cloudflare exposes certificate details as variables in the Ruleset Engine and as properties on the Workers `request.cf` object.

## Ruleset Engine fields

Client certificate fields are available as [mTLS fields](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/?field-category=mTLS) in Ruleset Engine-based products such as [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/) and [request header modification rules](https://developers.cloudflare.com/rules/transform/request-header-modification/).

## Workers variables

These variables are also available as part of the [request.cf.tlsClientAuth](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties) object via Cloudflare Workers. Refer to the linked Rules language field for the full definition.

Note

Some `tlsClientAuth` properties have a different type than their Rules language field equivalent. Those differences are called out in the following list.

* [request.cf.tlsClientAuth.certRevoked](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Frevoked/) — Indicates whether the mTLS client presented a valid but revoked client certificate. In Workers, this is a string (`"1"` for revoked, `"0"` for not revoked) rather than a boolean.
* [request.cf.tlsClientAuth.certVerified](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fverified/) — Indicates whether the mTLS client presented a valid client certificate. In Workers, this is a string (`"SUCCESS"` when valid, `"NONE"` when not present) rather than a boolean. On failure, the string contains the error reason (for example, `"FAILED:unable to get local issuer certificate"`).
* [request.cf.tlsClientAuth.certPresented](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fpresented/) — Indicates whether the mTLS client presented a certificate (valid or not). In Workers, this is a string (`"1"` when a certificate is presented, `"0"` otherwise) rather than a boolean.
* [request.cf.tlsClientAuth.certIssuerDN](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fissuer%5Fdn/) — The Distinguished Name (DN) of the Certificate Authority (CA) that issued the mTLS client certificate.
* [request.cf.tlsClientAuth.certSubjectDN](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fsubject%5Fdn/) — The Distinguished Name (DN) of the owner (or requester) of the mTLS client certificate.
* [request.cf.tlsClientAuth.certIssuerDNRFC2253](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fissuer%5Fdn%5Frfc2253/) — The Distinguished Name (DN) of the Certificate Authority (CA) that issued the mTLS client certificate in [RFC 2253 ↗](https://www.rfc-editor.org/rfc/rfc2253) format.
* [request.cf.tlsClientAuth.certSubjectDNRFC2253](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fsubject%5Fdn%5Frfc2253/) — The Distinguished Name (DN) of the owner (or requester) of the mTLS client certificate in [RFC 2253 ↗](https://www.rfc-editor.org/rfc/rfc2253) format.
* [request.cf.tlsClientAuth.certIssuerDNLegacy](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fissuer%5Fdn%5Flegacy/) — The Distinguished Name (DN) of the Certificate Authority (CA) that issued the mTLS client certificate in a legacy format.
* [request.cf.tlsClientAuth.certSubjectDNLegacy](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fsubject%5Fdn%5Flegacy/) — The Distinguished Name (DN) of the owner (or requester) of the mTLS client certificate in a legacy format.
* [request.cf.tlsClientAuth.certSerial](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fserial/) — Serial number of the mTLS client certificate.
* [request.cf.tlsClientAuth.certIssuerSerial](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fissuer%5Fserial/) — Serial number of the direct issuer of the mTLS client certificate.
* [request.cf.tlsClientAuth.certFingerprintSHA256](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Ffingerprint%5Fsha256/) — The SHA-256 fingerprint of the mTLS client certificate.
* [request.cf.tlsClientAuth.certFingerprintSHA1](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Ffingerprint%5Fsha1/) — The SHA-1 fingerprint of the mTLS client certificate.
* [request.cf.tlsClientAuth.certNotBefore](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fnot%5Fbefore/) — The mTLS client certificate is not valid before this date.
* [request.cf.tlsClientAuth.certNotAfter](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fnot%5Fafter/) — The mTLS client certificate is not valid after this date.
* [request.cf.tlsClientAuth.certSKI](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fski/) — The Subject Key Identifier (SKI) of the mTLS client certificate.
* [request.cf.tlsClientAuth.certIssuerSKI](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fissuer%5Fski/) — The Subject Key Identifier (SKI) of the direct issuer of the mTLS client certificate.
* [request.cf.tlsClientAuth.certRFC9440](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Frfc9440/) — The client leaf certificate encoded in [RFC 9440 ↗](https://www.rfc-editor.org/rfc/rfc9440) format (DER, Base64-encoded, colon-wrapped).
* [request.cf.tlsClientAuth.certRFC9440TooLarge](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Frfc9440%5Ftoo%5Flarge/) — `true` if the leaf certificate exceeded the 10 KiB encoding limit and was omitted from `certRFC9440`.
* [request.cf.tlsClientAuth.certChainRFC9440](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fchain%5Frfc9440/) — The intermediate certificate chain in [RFC 9440 ↗](https://www.rfc-editor.org/rfc/rfc9440) format as a comma-separated list.
* [request.cf.tlsClientAuth.certChainRFC9440TooLarge](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fchain%5Frfc9440%5Ftoo%5Flarge/) — `true` if the intermediate chain exceeded the 16 KiB encoding limit and was omitted from `certChainRFC9440`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/client-certificates/","name":"Client certificates (mTLS)"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/client-certificates/client-certificate-variables/","name":"Client certificate variables"}}]}
```

---

---
title: Configure your mobile app or IoT device
description: This tutorial demonstrates how to configure your Internet-of-things (IoT) device and mobile application to use client certificates with API Shield.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configure your mobile app or IoT device

This tutorial demonstrates how to configure your Internet-of-things (IoT) device and mobile application to use client certificates with [API Shield](https://developers.cloudflare.com/api-shield/).

## Scenario details

This walkthrough uses the example of a device that captures temperature readings and transmits them by sending a POST request to a Cloudflare-protected API. A mobile application built in Swift for iOS retrieves those readings and displays them.

To keep this example simple, the API is implemented as a Cloudflare Worker (borrowing code from the [To-Do List tutorial on building a jamstack app](https://developers.cloudflare.com/workers/tutorials/build-a-jamstack-app/)).

Temperatures are stored in [Workers KV](https://developers.cloudflare.com/kv/concepts/how-kv-works/) using the source IP address as a key, but you can easily use a [value from the client certificate](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/mutual-tls-authentication/), such as the fingerprint.

The example API code below saves a temperature and timestamp into KV when a POST is made and returns the most recent five temperatures when a GET request is made.

JavaScript

```

const defaultData = { temperatures: [] };


const getCache = (key) => TEMPERATURES.get(key);

const setCache = (key, data) => TEMPERATURES.put(key, data);


async function addTemperature(request) {

  // Pull previously recorded temperatures for this client.

  const ip = request.headers.get("CF-Connecting-IP");

  const cacheKey = `data-${ip}`;

  let data;

  const cache = await getCache(cacheKey);

  if (!cache) {

    await setCache(cacheKey, JSON.stringify(defaultData));

    data = defaultData;

  } else {

    data = JSON.parse(cache);

  }


  // Append the recorded temperatures with the submitted reading (assuming it has both temperature and a timestamp).

  try {

    const body = await request.text();

    const val = JSON.parse(body);


    if (val.temperature && val.time) {

      data.temperatures.push(val);

      await setCache(cacheKey, JSON.stringify(data));

      return new Response("", { status: 201 });

    } else {

      return new Response(

        "Unable to parse temperature and/or timestamp from JSON POST body",

        { status: 400 },

      );

    }

  } catch (err) {

    return new Response(err, { status: 500 });

  }

}


function compareTimestamps(a, b) {

  return -1 * (Date.parse(a.time) - Date.parse(b.time));

}


// Return the 5 most recent temperature measurements.

async function getTemperatures(request) {

  const ip = request.headers.get("CF-Connecting-IP");

  const cacheKey = `data-${ip}`;


  const cache = await getCache(cacheKey);

  if (!cache) {

    return new Response(JSON.stringify(defaultData), {

      status: 200,

      headers: { "content-type": "application/json" },

    });

  } else {

    data = JSON.parse(cache);

    const retval = JSON.stringify(

      data.temperatures.sort(compareTimestamps).splice(0, 5),

    );

    return new Response(retval, {

      status: 200,

      headers: { "content-type": "application/json" },

    });

  }

}


export default {

  async fetch(request, env, ctx) {

    return request.method === "POST"

      ? addTemperature(request)

      : getTemperatures(request);

  },

};


```

---

## 1\. Validate API

### POST sample data to API

To validate the API before adding mTLS authentication, POST a random temperature reading:

Terminal window

```

$ TEMPERATURE=$(echo $((361 + RANDOM %11)) | awk '{printf("%.2f",$1/10.0)}')

$ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")


$ echo -e "$TEMPERATURE\n$TIMESTAMP"

36.70

2020-09-28T02:54:56Z


$ curl --verbose --header "Content-Type: application/json" --data '{"temperature":'''$TEMPERATURE''', "time": "'''$TIMESTAMP'''"}' https://shield.upinatoms.com/temps 2>&1 | grep "< HTTP/2"

< HTTP/2 201


```

### GET sample data from API

A GET request to the `temps` endpoint returns the most recent readings, including the one submitted in the example above:

Terminal window

```

$ curl --silent https://shield.upinatoms.com/temps | jq .

[

  {

    "temperature": 36.3,

    "time": "2020-09-28T02:57:49Z"

  },

  {

    "temperature": 36.7,

    "time": "2020-09-28T02:54:56Z"

  },

  {

    "temperature": 36.2,

    "time": "2020-09-28T02:33:08Z"

  }

]


```

---

## 2\. Create Cloudflare-issued certificates

Before you can use API Shield to protect your API or web application, create Cloudflare-issued client certificates.

You can [create a client certificate in the Cloudflare dashboard](https://developers.cloudflare.com/ssl/client-certificates/create-a-client-certificate/).

However, since most developers working at scale generate their own private keys and certificate signing requests via API, this example uses the Cloudflare API to create client certificates.

To create a bootstrap certificate for the iOS application and the IoT device, this example uses [Cloudflare’s public key infrastructure toolkit, CFSSL ↗](https://github.com/cloudflare/cfssl):

Terminal window

```

# Generate a private key and CSR for the iOS device.


$ cat <<'EOF' | tee -a csr.json

{

    "hosts": [

        "ios-bootstrap.devices.upinatoms.com"

    ],

    "CN": "ios-bootstrap.devices.upinatoms.com",

    "key": {

        "algo": "rsa",

        "size": 2048

    },

    "names": [{

        "C": "US",

        "L": "Austin",

        "O": "Temperature Testers, Inc.",

        "OU": "Tech Operations",

        "ST": "Texas"

    }]

}

EOF


$ cfssl genkey csr.json | cfssljson -bare certificate


2020/09/27 21:28:46 [INFO] generate received request

2020/09/27 21:28:46 [INFO] received CSR

2020/09/27 21:28:46 [INFO] generating key: rsa-2048

2020/09/27 21:28:47 [INFO] encoded CSR


$ mv certificate-key.pem ios-key.pem

$ mv certificate.csr ios.csr


# Do the same for the IoT sensor.


$ sed -i.bak 's/ios-bootstrap/sensor-001/g' csr.json

$ cfssl genkey csr.json | cfssljson -bare certificate

...

$ mv certificate-key.pem sensor-key.pem

$ mv certificate.csr sensor.csr


# now ask that these CSRs be signed by the private CA issued for your zone

# we need to replace actual newlines in the CSR with ‘\n’ before POST’ing

$ CSR=$(cat ios.csr | perl -pe 's/\n/\\n/g')

$ request_body=$(< <(cat <<EOF

{

  "validity_days": 3650,

  "csr":"$CSR"

}

EOF

))


# save the response so we can view it and then extra the certificate

$ curl https://api.cloudflare.com/client/v4/zones/{zone_id}/client_certificates \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data "$request_body" > response.json


$ cat response.json | jq .


{

  "success": true,

  "errors": [],

  "messages": [],

  "result": {

    "id": "7bf7f70c-7600-42e1-81c4-e4c0da9aa515",

    "certificate_authority": {

      "id": "8f5606d9-5133-4e53-b062-a2e5da51be5e",

      "name": "Cloudflare Managed CA for account 11cbe197c050c9e422aaa103cfe30ed8"

    },

    "certificate": "-----BEGIN CERTIFICATE-----\nMIIEkzCCA...\n-----END CERTIFICATE-----\n",

    "csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIIDITCCA...\n-----END CERTIFICATE REQUEST-----\n",

    "ski": "eb2a48a19802a705c0e8a39489a71bd586638fdf",

    "serial_number": "133270673305904147240315902291726509220894288063",

    "signature": "SHA256WithRSA",

    "common_name": "ios-bootstrap.devices.upinatoms.com",

    "organization": "Temperature Testers, Inc.",

    "organizational_unit": "Tech Operations",

    "country": "US",

    "state": "Texas",

    "location": "Austin",

    "expires_on": "2030-09-26T02:41:00Z",

    "issued_on": "2020-09-28T02:41:00Z",

    "fingerprint_sha256": "84b045d498f53a59bef53358441a3957de81261211fc9b6d46b0bf5880bdaf25",

    "validity_days": 3650

  }

}


$ cat response.json | jq .result.certificate | perl -npe 's/\\n/\n/g; s/"//g' > ios.pem


# Now ask that the second client certificate signing request be signed.


$ CSR=$(cat sensor.csr | perl -pe 's/\n/\\n/g')

$ request_body=$(< <(cat <<EOF

{

  "validity_days": 3650,

  "csr":"$CSR"

}

EOF

))


$ curl https://api.cloudflare.com/client/v4/zones/{zone_id}/client_certificates \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data "$request_body" | perl -npe 's/\\n/\n/g; s/"//g' > sensor.pem


```

---

## 3\. Embed the client certificate in your mobile app

To configure the mobile app to securely request temperature data submitted by the IoT device, embed the client certificate in the mobile app.

For simplicity, this example embeds a “bootstrap” certificate and key in the application bundle as a PKCS#12-formatted file:

Terminal window

```

$ openssl pkcs12 -export -out bootstrap-cert.pfx -inkey ios-key.pem -in ios.pem

Enter Export Password:

Verifying - Enter Export Password:


```

In a real-world deployment, a bootstrap certificate should only be used in conjunction with users' credentials to authenticate with an API endpoint that can return a unique user certificate. Corporate users will want to use mobile device management (MDM) to distribute certificates.

### Embed the client certificate in an Android app

The following is an example of how you may use a client certificate in an Android app to make HTTP calls. You need to add the following permission in `AndroidManifest.xml` to allow an Internet connection.

```

<uses-permission android:name="android.permission.INTERNET" />


```

For demonstration purposes, the certificate in this example is stored in `app/src/main/res/raw/cert.pem` and the private key is stored in `app/src/main/res/raw/key.pem`. You may also store these files in other secure manners.

The following example uses an `OkHttpClient`, but you may also use other clients such as `HttpURLConnection` in similar ways. The key is to use the `SSLSocketFactory`.

```

private OkHttpClient setUpClient() {

    try {

        final String SECRET = "secret"; // You may also store this String somewhere more secure.

        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");


        // Get private key

        InputStream privateKeyInputStream = getResources().openRawResource(R.raw.key);

        byte[] privateKeyByteArray = new byte[privateKeyInputStream.available()];

        privateKeyInputStream.read(privateKeyByteArray);


        String privateKeyContent = new String(privateKeyByteArray, Charset.defaultCharset())

                .replace("-----BEGIN PRIVATE KEY-----", "")

                .replaceAll(System.lineSeparator(), "")

                .replace("-----END PRIVATE KEY-----", "");


        byte[] rawPrivateKeyByteArray = Base64.getDecoder().decode(privateKeyContent);

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rawPrivateKeyByteArray);


        // Get certificate

        InputStream certificateInputStream = getResources().openRawResource(R.raw.cert);

        Certificate certificate = certificateFactory.generateCertificate(certificateInputStream);


        // Set up KeyStore

        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

        keyStore.load(null, SECRET.toCharArray());

        keyStore.setKeyEntry("client", keyFactory.generatePrivate(keySpec), SECRET.toCharArray(), new Certificate[]{certificate});

        certificateInputStream.close();


        // Set up Trust Managers

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

        trustManagerFactory.init((KeyStore) null);

        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();


        // Set up Key Managers

        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

        keyManagerFactory.init(keyStore, SECRET.toCharArray());

        KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();


        // Obtain SSL Socket Factory

        SSLContext sslContext = SSLContext.getInstance("TLS");

        sslContext.init(keyManagers, trustManagers, new SecureRandom());

        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();


        // Finally, return the client, which will then be used to make HTTP calls.

        OkHttpClient client = new OkHttpClient.Builder()

                .sslSocketFactory(sslSocketFactory, (X509TrustManager) trustManagers[0])

                .build();


        return client;


    } catch (CertificateException | IOException | NoSuchAlgorithmException | KeyStoreException | UnrecoverableKeyException | KeyManagementException | InvalidKeySpecException e) {

        e.printStackTrace();

        return null;

    }

}


```

The above function returns an `OkHttpClient` embedded with the client certificate. You can now use this client to make HTTP requests to your API endpoint protected with mTLS.

---

## 4\. Embed the client certificate on your IoT device

To prepare the IoT device for secure communication with the API endpoint, embed the certificate on the device and configure the device to use the certificate when making POST requests.

This example assumes the certificate and the private key are securely copied to `/etc/ssl/private/sensor-key.pem` and `/etc/ssl/certs/sensor.pem`.

The sample script is modified to point to these files:

Python

```

import requests

import json

from datetime import datetime


def readSensor():


    # Takes a reading from a temperature sensor and store it to temp_measurement


    dateTimeObj = datetime.now()

    timestampStr = dateTimeObj.strftime('%Y-%m-%dT%H:%M:%SZ')


    measurement = {'temperature':str(temp_measurement),'time':timestampStr}

    return measurement


def main():


    print("Cloudflare API Shield [IoT device demonstration]")


    temperature = readSensor()

    payload = json.dumps(temperature)


    url = 'https://shield.upinatoms.com/temps'

    json_headers = {'Content-Type': 'application/json'}

    cert_file = ('/etc/ssl/certs/sensor.pem', '/etc/ssl/private/sensor-key.pem')


    r = requests.post(url, headers = json_headers, data = payload, cert = cert_file)


    print("Request body: ", r.request.body)

    print("Response status code: %d" % r.status_code)


```

When the script attempts to connect to `https://shield.upinatoms.com/temps`, Cloudflare requests that a client certificate is sent and the script sends the contents of `/etc/ssl/certs/sensor.pem`. Then, as required to complete the SSL/TLS handshake, the script demonstrates it has possession of `/etc/ssl/private/sensor-key.pem`.

Without the client certificate, the Cloudflare rejects the request:

```

Cloudflare API Shield [IoT device demonstration]

Request body:  {"temperature": "36.5", "time": "2020-09-28T15:52:19Z"}

Response status code: 403


```

When the IoT device presents a valid client certificate, the POST request succeeds and the temperature reading is recorded:

```

Cloudflare API Shield [IoT device demonstration]

Request body:  {"temperature": "36.5", "time": "2020-09-28T15:56:45Z"}

Response status code: 201


```

---

## 5\. Enable mTLS

After creating Cloudflare-issued certificates, the next step is to [enable mTLS](https://developers.cloudflare.com/ssl/client-certificates/enable-mtls/) for the hosts you want to protect with API Shield.

---

## 6\. Configure API Shield to require client certificates

To configure API Shield to require client certificates, [create a mTLS rule](https://developers.cloudflare.com/api-shield/security/mtls/configure/#create-an-mtls-rule).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/client-certificates/","name":"Client certificates (mTLS)"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/client-certificates/configure-your-mobile-app-or-iot-device/","name":"Configure your mobile app or IoT device"}}]}
```

---

---
title: Create a client certificate
description: Generate a client certificate using the dashboard or API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Create a client certificate

Use Cloudflare's public key infrastructure (PKI) to create client certificates issued from a Cloudflare-managed CA. You can then complete your mTLS configuration, as explained in [How mTLS works](https://developers.cloudflare.com/ssl/client-certificates/#how-it-works).

Cloudflare-issued or BYOCA

The following process only refers to certificates issued from the Cloudflare-managed CA. To bring your own CA, refer to [BYOCA](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/) instead. Only available to Enterprise accounts.

To create a client certificate on the Cloudflare dashboard:

1. Go to the **Client Certificates** page.  
[ Go to **Client Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. Select **Add Certificate**. The Cloudflare-managed CA is the default **Certificate Authority**.
3. Fill in the required fields. You can choose one of the following options:
* Generate a private key and Certificate Signing Request (CSR) with Cloudflare.
* Use your own private key and CSR. This option allows you to also [label client certificates](https://developers.cloudflare.com/ssl/client-certificates/label-client-certificate/).  
Example OpenSSL command  
To generate and use your own CSR, you can run a command like the following:  
Terminal window  
```  
openssl req -new -newkey rsa:2048 -nodes -keyout client1.key -out client1.csr -subj '/C=GB/ST=London/L=London/O=Organization/CN=CommonName'  
```
1. Select a value for **Certificate Validity**, and choose **Continue**.
2. Make sure to copy the certificate and private key as they will no longer be displayed after creation.
3. (Optional) Specify hostnames where you wish to [enable mTLS](https://developers.cloudflare.com/ssl/client-certificates/enable-mtls/).  
When associating hostnames via this form, they should be in fully qualified domain name (FQDN) format and correspond to a hostname that exists in the zone you are in. For example, if you are in zone `example.com`, you can specify `host.example.com` but not `host.example.net`.
4. Select **Save** to confirm.

## Next steps

After creating the client certificate, make sure it is installed on the client devices and [enable mTLS](https://developers.cloudflare.com/ssl/client-certificates/enable-mtls/) for each hostname that should require a certificate from clients.

Refer to our [mTLS at Cloudflare learning path](https://developers.cloudflare.com/learning-paths/mtls/concepts/) for further context.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/client-certificates/","name":"Client certificates (mTLS)"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/client-certificates/create-a-client-certificate/","name":"Create a client certificate"}}]}
```

---

---
title: Enable mTLS
description: Enable mutual TLS to require client certificates for your host.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Enable mTLS

You can enable mutual Transport Layer Security (mTLS) for any hostname. For more information, refer to the [Client certificates overview](https://developers.cloudflare.com/ssl/client-certificates/).

Cloudflare-issued or BYOCA

The following process only refers to certificates issued from the Cloudflare-managed CA. For hostnames that should be validated using your own CA, refer to the [BYOCA documentation](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/).

To enable mTLS for a host from the Cloudflare dashboard:

1. In the Cloudflare dashboard, go to the **Client Certificates** page.  
[ Go to **Client Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. On the **Hosts** section of the **Client Certificates** card, select **Edit**.
3. Enter the name of a host in your current domain.  
Note  
The domain (`example.com`) is automatically appended for you. This means that, if you want to enable mTLS for `abc.example.com`, you only need to type `abc`.
4. Select **Save** to confirm.

## CAs in use

As explained in the [Client certificates overview](https://developers.cloudflare.com/ssl/client-certificates/#how-it-works), Cloudflare validates client certificates against CAs set at account level. This means that these certificates can be used for validation across multiple zones/domains (`example.com`), as long as the zones are under the same Cloudflare account and you have enabled mTLS for the host.

Bring your own CA

If you need to use your own CA (instead of the Cloudflare-managed CA), refer to [BYOCA](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/). This option is available on Enterprise accounts.

## Next steps

After enabling mTLS for your host, you can:

* Enforce mTLS with a WAF custom rule. Select **Create mTLS Rule** on the dashboard to use a template, or refer to our [mTLS at Cloudflare learning path](https://developers.cloudflare.com/learning-paths/mtls/mtls-app-security/#3-validate-the-client-certificate-in-the-waf) for further guidance.
* Enforce mTLS with [API Shield](https://developers.cloudflare.com/api-shield/security/mtls/configure/). While API Shield is **not required** to use mTLS, many teams may use mTLS to protect their APIs.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/client-certificates/","name":"Client certificates (mTLS)"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/client-certificates/enable-mtls/","name":"Enable mTLS"}}]}
```

---

---
title: Forward certificate to server
description: Forward client certificate details to your origin server.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Forward certificate to server

## Add Client-Cert and Client-Cert-Chain headers (RFC 9440)

[RFC 9440 ↗](https://datatracker.ietf.org/doc/html/rfc9440) defines the `Client-Cert` and `Client-Cert-Chain` HTTP header fields for passing client certificate information to origin servers. You can construct these headers using [request header modification rules](https://developers.cloudflare.com/rules/transform/request-header-modification/) with the following Ruleset Engine fields:

* [cf.tls\_client\_auth.cert\_rfc9440](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Frfc9440/) — The client leaf certificate encoded in RFC 9440 formatting (see reference).
* [cf.tls\_client\_auth.cert\_chain\_rfc9440](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fchain%5Frfc9440/) — The certificate chain (excluding the leaf certificate) encoded in RFC 9440 formatting (see reference).

As indicated in field definitions, the fields may be set to either an empty string or a valid RFC 9440 encoding. Proper usage depends on a couple of factors discussed in the following sections.

### Security considerations

Important

Before constructing `Client-Cert` or `Client-Cert-Chain` headers, you must address the following security concerns. Failing to do so can expose your origin server to forged or unverified certificate data.

The `cert_rfc9440` and `cert_chain_rfc9440` fields are populated **regardless of the certificate validation result**. This means a client can present an invalid, expired, or self-signed certificate, and the fields will still contain the encoded certificate data. Always check the following fields before trusting the values:

* [cf.tls\_client\_auth.cert\_verified](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fverified/) — Returns `true` when the client certificate is valid.
* [cf.tls\_client\_auth.cert\_revoked](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Frevoked/) — Returns `true` when the client certificate has been revoked.

A client can also include its own `Client-Cert` or `Client-Cert-Chain` headers on a request to inject arbitrary values. As described in the [RFC 9440 security considerations ↗](https://datatracker.ietf.org/doc/html/rfc9440#name-security-considerations), you must unconditionally remove any existing `Client-Cert` and `Client-Cert-Chain` headers from incoming requests, regardless of certificate validity. This prevents a client from injecting forged certificate data that your origin would trust.

See [Enable mTLS](https://developers.cloudflare.com/ssl/client-certificates/enable-mtls/) for details on how to configure mTLS and certificate validation.

### Size limits

The encoded leaf certificate is limited to 10 KiB and the encoded chain is limited to 16 KiB. If the encoded value exceeds the limit, the corresponding field contains an empty string. Use the following fields to check for this condition:

* [cf.tls\_client\_auth.cert\_rfc9440\_too\_large](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Frfc9440%5Ftoo%5Flarge/) — Returns `true` when the encoded certificate exceeds 10 KiB.
* [cf.tls\_client\_auth.cert\_chain\_rfc9440\_too\_large](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fchain%5Frfc9440%5Ftoo%5Flarge/) — Returns `true` when the encoded chain exceeds 16 KiB.

### Example Transform Rules

Here we provide an example on how to securely use these fields to construct trusted `Client-Cert` and `Client-Cert-Chain` headers to be forwarded to your origin. The origin can then rely on the presence of the headers to be certain the client presented a valid certificate. Note: the `Client-Cert-Chain` header may be omitted when the client did not present any intermediates (only a leaf certificate).

You need to create the following request header modification rules. The **Remove** rules must be placed before the **Set dynamic** rules so that client-injected headers are stripped on every request before the validated values are set.

#### Rule 1 — Remove Client-Cert header

This rule unconditionally removes any `Client-Cert` header sent by the client.

Text in **Expression Editor**:

```

true


```

Selected operation under **Modify request header**: _Remove_

**Header name**: `Client-Cert`

#### Rule 2 — Remove Client-Cert-Chain header

This rule unconditionally removes any `Client-Cert-Chain` header sent by the client.

Text in **Expression Editor**:

```

true


```

Selected operation under **Modify request header**: _Remove_

**Header name**: `Client-Cert-Chain`

#### Rule 3 — Set Client-Cert header

This rule sets the `Client-Cert` header only when the client presented a valid, non-revoked certificate that is within the size limit.

Text in **Expression Editor**:

```

cf.tls_client_auth.cert_verified

and not cf.tls_client_auth.cert_revoked

and not cf.tls_client_auth.cert_rfc9440_too_large


```

Selected operation under **Modify request header**: _Set dynamic_

**Header name**: `Client-Cert`

**Value**: `cf.tls_client_auth.cert_rfc9440`

#### Rule 4 — Set Client-Cert-Chain header

This rule sets the `Client-Cert-Chain` header only when the client presented a valid, non-revoked certificate and the chain is non-empty and within the size limit.

Text in **Expression Editor**:

```

cf.tls_client_auth.cert_verified

and not cf.tls_client_auth.cert_revoked

and cf.tls_client_auth.cert_chain_rfc9440 ne ""

and not cf.tls_client_auth.cert_chain_rfc9440_too_large


```

Selected operation under **Modify request header**: _Set dynamic_

**Header name**: `Client-Cert-Chain`

**Value**: `cf.tls_client_auth.cert_chain_rfc9440`

### Cloudflare Workers

You can also construct RFC 9440 headers in a [Cloudflare Worker](https://developers.cloudflare.com/workers/)using the [tlsClientAuth](https://developers.cloudflare.com/ssl/client-certificates/client-certificate-variables/#workers-variables)properties on the incoming request.

The same security considerations mentioned above apply.

## Forward a client certificate (legacy)

In addition to enforcing mTLS authentication for your host, you can also forward a client certificate to your origin server as an HTTP header. This setup is often helpful for server logging.

To avoid adding the certificate to every single request, the certificate is only forwarded on the first request of an mTLS connection.

Warning

This process is only available on accounts with [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/).

### Cloudflare API

The most common approach to forwarding a certificate is to use the Cloudflare API to [update an mTLS certificate's hostname settings](https://developers.cloudflare.com/api/resources/zero%5Ftrust/subresources/access/subresources/certificates/subresources/settings/methods/update/).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Access: Mutual TLS Certificates Write`

Update an mTLS certificate's hostname settings

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/access/certificates/settings" \

  --request PUT \

  --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \

  --header "X-Auth-Key: $CLOUDFLARE_API_KEY" \

  --json '{

    "settings": [

        {

            "hostname": "<HOSTNAME>",

            "china_network": false,

            "client_certificate_forwarding": true

        }

    ]

  }'


```

Once `client_certificate_forwarding` is set to `true`, every request within an mTLS connection will now include the following headers:

* `Cf-Client-Cert-Der-Base64`
* `Cf-Client-Cert-Sha256`

Note

The `Cf-Client-Cert-Der-Base64` and `Cf-Client-Cert-Sha256` headers are a Cloudflare-proprietary mechanism. For a standardized approach, use [RFC 9440 Client-Cert and Client-Cert-Chain headers](https://developers.cloudflare.com/ssl/client-certificates/forward-a-client-certificate/#add-client-cert-and-client-cert-chain-headers-rfc-9440).

### Managed Transforms

You can also [modify HTTP response headers](https://developers.cloudflare.com/rules/transform/response-header-modification/) using Managed Transforms to pass along **TLS client auth headers**.

### Cloudflare Workers

Additionally, Workers can provide details around the [client certificate](https://developers.cloudflare.com/workers/runtime-apis/bindings/mtls/).

JavaScript

```

const tlsHeaders = {

  "X-CERT-ISSUER-DN": request.cf.tlsClientAuth.certIssuerDN,

  "X-CERT-SUBJECT-DN": request.cf.tlsClientAuth.certSubjectDN,

  "X-CERT-ISSUER-DN-L": request.cf.tlsClientAuth.certIssuerDNLegacy,

  "X-CERT-SUBJECT-DN-L": request.cf.tlsClientAuth.certSubjectDNLegacy,

  "X-CERT-SERIAL": request.cf.tlsClientAuth.certSerial,

  "X-CERT-FINGER": request.cf.tlsClientAuth.certFingerprintSHA1,

  "X-CERT-VERIFY": request.cf.tlsClientAuth.certVerify,

  "X-CERT-NOTBE": request.cf.tlsClientAuth.certNotBefore,

  "X-CERT-NOTAF": request.cf.tlsClientAuth.certNotAfter,

};


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/client-certificates/","name":"Client certificates (mTLS)"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/client-certificates/forward-a-client-certificate/","name":"Forward certificate to server"}}]}
```

---

---
title: Label client certificates
description: Organize client certificates with labels for easier management.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Label client certificates

After [creating client certificates](https://developers.cloudflare.com/ssl/client-certificates/) at Cloudflare, it may be hard to differentiate the generated certificates.

## Root Cause

The option to generate private key and CSR with Cloudflare is meant for simpler cases and the certificates will be generated with just "CN=Cloudflare, C=US".

## Solution

If you need to differentiate client certificates for your clients on a per-organization basis, you can generate your own private key and CSR. When you generate the private key and CSR, you can then enter information that will be incorporated into your certificate request.

For example, if you run the following command (with OpenSSL installed):

Terminal window

```

openssl req -new -newkey rsa:2048 -nodes -keyout client1.key -out client1.csr


```

You can then specify:

```

Country Name (2 letter code) []:

State or Province Name (full name) []:

Locality Name (eg, city) []:

Organization Name (eg, company) []:

Organizational Unit Name (eg, section) []:

Common Name (eg, fully qualified host name) []:

Email Address []:


```

Usually, adding `Country Name` and `Organization Name` is enough, but you can provide as much information as you need or want.

The additional information will be included in the **Certificate Subject**, allowing you to easily identify which certificate belongs to which client. This can also make it easier to revoke a specific certificate when needed.

The following image displays an example of how a certificate with with `Country Name`, `Organization Name`, and `Organizational Unit Name` will look like on the Cloudflare dashboard:

![](https://developers.cloudflare.com/_astro/chrome_mQRJVOpkTQ.BiKeZMXO_sl7oA.webp) 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/client-certificates/","name":"Client certificates (mTLS)"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/client-certificates/label-client-certificate/","name":"Label client certificates"}}]}
```

---

---
title: Revoke a client certificate
description: Revoke a client certificate to block its use.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Revoke a client certificate

You can revoke a client certificate you previously generated with the default [Cloudflare-managed CA](https://developers.cloudflare.com/ssl/client-certificates/).

It is not possible to permanently delete client certificates generated with the default Cloudflare-managed CA. Once revoked, these client certificates will still be listed on the [**Client Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates) page, and can be restored at any time.

## Steps

1. In the Cloudflare dashboard, go to the **Client Certificates** page.  
[ Go to **Client Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. Select the certificate you want to revoke.
3. Select **Revoke** and confirm the operation.

Important

After revoking a certificate, you must update any mTLS rules that check for the presence of a client certificate so that they block all requests that include a revoked certificate.

For more information, refer to [Check for revoked certificates](https://developers.cloudflare.com/api-shield/security/mtls/configure/#check-for-revoked-certificates).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/client-certificates/","name":"Client certificates (mTLS)"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/client-certificates/revoke-client-certificate/","name":"Revoke a client certificate"}}]}
```

---

---
title: Troubleshooting
description: Troubleshoot issues with client certificates
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

If your query returns an error even after configuring and embedding a client SSL certificate, check the following settings.

Note

Before troubleshooting, disable VPNs and proxies. These can interfere with the mTLS handshake.

---

## Check SSL/TLS handshake

On your terminal, use the following command to check whether an SSL/TLS connection can be established successfully between the client and the API endpoint.

Terminal window

```

curl --verbose --cert /path/to/certificate.pem --key /path/to/key.pem https://your-api-endpoint.com


```

If the SSL/TLS handshake cannot be completed, check whether the certificate and the private key are correct. If the handshake completes but requests are still blocked, confirm that Cloudflare is verifying the client certificate.

---

## Check mTLS hosts

Check whether [mTLS has been enabled](https://developers.cloudflare.com/ssl/client-certificates/enable-mtls/) for the correct host. The host should match the API endpoint that you want to protect.

---

## Review mTLS rules

To review mTLS rules, consider the steps below. For further guidance refer to [Custom rules](https://developers.cloudflare.com/waf/custom-rules/create-dashboard/).

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. On a specific rule, select **Edit**.
3. On that rule, check whether:  
   * The Expression Preview is correct.  
   * The hostname, if defined, matches your API endpoint. For example, for the API endpoint `api.trackers.ninja/time`, the rule should look like:  
   ```  
   (http.host in {"api.trackers.ninja"} and not cf.tls_client_auth.cert_verified)  
   ```
4. To edit the rule, either use the user interface or select **Edit expression**.

---

## Advanced debugging

You can use [Cloudflare Workers](https://developers.cloudflare.com/workers/) to debug client certificate validation failures.

1. Create a Worker to debug print [cf.properties](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties):  
JavaScript  
```  
export default {  
  async fetch(request, env, ctx) {  
    console.info({ message: JSON.stringify(request.cf, null, 2) });  
    return new Response(JSON.stringify(request.cf, null, 2))  
  }  
};  
```
2. Associate the Worker with the hostname where mTLS is enabled using a [Worker route](https://developers.cloudflare.com/workers/configuration/routing/routes/) or a [Custom Domain](https://developers.cloudflare.com/workers/configuration/routing/custom-domains/).
3. Make requests to the hostname and/or path configured, with and without sending the mTLS client certificate.
4. View your logs on the [Observability](https://developers.cloudflare.com/workers/observability/) dashboard and compare the responses against the expected values listed below.  
[ Go to **Observability** ](https://dash.cloudflare.com/?to=/:account/workers-and-pages/observability)
* Valid certificate  
```  
"tlsClientAuth": {  
  "certPresented": "1",  
  "certVerified": "SUCCESS",  
},  
```
* Invalid certificate (for example, self-signed certificates)  
```  
"tlsClientAuth": {  
  "certPresented": "1",  
  "certVerified": "FAILED:self signed certificate",  
},  
```
* No certificate  
```  
"tlsClientAuth": {  
  "certPresented": "0",  
  "certVerified": "NONE",  
},  
```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/client-certificates/","name":"Client certificates (mTLS)"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/client-certificates/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: Mutual TLS
description: Mutual TLS in Access.
image: https://developers.cloudflare.com/zt-preview.png
---

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

[Skip to content](#%5Ftop) 

# Mutual TLS

[Mutual TLS (mTLS) authentication ↗](https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/) requires both the client and the server to present certificates during the TLS handshake. In the Cloudflare Access implementation, the CA you upload is used to verify the client certificate (server certificate verification is handled by standard TLS). Access mTLS serves two purposes:

* **Authenticate devices that do not use an identity provider** — Automated systems and IoT devices can prove their identity by presenting a client certificate instead of logging in through an IdP.
* **Add a second authentication factor** — Team members who log in through an IdP can also be required to present a valid client certificate, providing an additional layer of security.

When you upload a root certificate authority (CA) to Access, only requests from devices with a matching client certificate are allowed through. When a request reaches the application, Access asks the client to present a certificate. If the client cannot present a valid certificate, the request is blocked. If the client presents a valid certificate, Access completes a key exchange to verify.

![mTLS handshake diagram](https://developers.cloudflare.com/_astro/mtls.BbZYLY1o_tux4L.webp) 

Important

The mTLS certificate is used only to verify the client certificate. It does not control the SSL certificate presented during the [server hello ↗](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/).

## Enforce mTLS authentication

### Prerequisites

* An [Access application](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app/) for the hostname that you would like to secure with mTLS.
* A CA that issues client certificates for your devices.  
   * The CA certificate can be from a publicly trusted CA or self-signed.  
   * In the certificate `Basic Constraints`, the attribute `CA` must be set to `TRUE`.  
   * The certificate must use one of the signature algorithms listed below:  
   Allowed signature algorithms  
   `x509.SHA1WithRSA`  
   `x509.SHA256WithRSA`  
   `x509.SHA384WithRSA`  
   `x509.SHA512WithRSA`  
   `x509.ECDSAWithSHA1`  
   `x509.ECDSAWithSHA256`  
   `x509.ECDSAWithSHA384`  
   `x509.ECDSAWithSHA512`

### Add mTLS to your Access application

1. In the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), go to **Zero Trust** \> **Access controls** \> **Service credentials** \> **Mutual TLS**.
2. Select **Add mTLS Certificate**.
3. Enter any name for the root CA.
4. In **Certificate content**, paste the contents of your root CA.  
If the client certificate is directly signed by the root CA, you only need to upload the root. If the client certificate is signed by an intermediate certificate, you must upload the entire CA chain (intermediate and root). For example:  
```  
-----BEGIN CERTIFICATE-----  
<intermediate.pem>  
-----END CERTIFICATE-----  
-----BEGIN CERTIFICATE-----  
<rootCA.pem>  
-----END CERTIFICATE-----  
```  
 Do not include any SSL/TLS server certificates; Access only uses the CA chain to verify the connection between the user's device and Cloudflare.
1. In **Associated hostnames**, enter the fully-qualified domain names (FQDN) that will use this certificate.  
These FQDNs will be the hostnames used for the resources being protected in the [Access policy](https://developers.cloudflare.com/cloudflare-one/access-controls/policies/). You must associate the Root CA with the FQDN that the application being protected uses.
2. Save the policy.
3. Go to **Access controls** \> **Policies**.
4. [Create an Access policy](https://developers.cloudflare.com/cloudflare-one/access-controls/policies/policy-management/#create-a-policy) using one of the following [selectors](https://developers.cloudflare.com/cloudflare-one/access-controls/policies/#selectors):  
   * **Valid Certificate**: Any client certificate that can authenticate with the Root CA will be allowed to proceed.  
   * **Common Name**: Only client certificates with a specific common name will be allowed to proceed.
5. If this is for a client who does not need to log in through an IdP, set the policy **Action** to _Service Auth_.  
**Example mTLS policy**  
| Action       | Rule type | Selector    | Value    |  
| ------------ | --------- | ----------- | -------- |  
| Service Auth | Include   | Common Name | John Doe |
6. Save the policy, then go to **Access controls** \> **Applications**.
7. Select the application you would like to enforce mTLS on and select **Configure**. The application must be included in the **Associated hostnames** list from Step 5.
8. In the **Policies** tab, add your mTLS policy.
9. Save the application.

You can now authenticate to the application using a client certificate. For instructions on how to present a client certificate, refer to [Test mTLS](#test-mtls).

## Test mTLS

### Test using cURL

To test the application protected by an mTLS policy:

1. First, attempt to curl the site without a client certificate. This curl command example is for the site `example.com` that has an [Access application and policy](#add-mtls-to-your-access-application) set for `https://auth.example.com`:  
Terminal window  
```  
curl -sv https://auth.example.com  
```  
Without a client certificate in the request, a `403 forbidden` response displays and the site cannot be accessed.
2. Now, add your client certificate and key to the request:  
Terminal window  
```  
curl -sv https://auth.example.com --cert example.pem --key key.pem  
```

When the authentication process completes successfully, a `CF_Authorization Set-Cookie` header returns in the response.

Warning

Cloudflare Gateway cannot inspect traffic to mTLS-protected domains. If a device has the Cloudflare One Client turned on and passes HTTP requests through Gateway, access will be blocked unless you [bypass HTTP inspection](https://developers.cloudflare.com/cloudflare-one/traffic-policies/http-policies/#do-not-inspect) for the domain.

### Test in a browser

To access an mTLS-protected application in a browser, the client certificate must be imported into your browser's certificate manager. Instructions vary depending on the browser. Your browser may use the operating system's root store or its own internal trust store.

The following example demonstrates how to add a client certificate to the macOS system keychain:

Important

The command adds the client certificate to the trusted store on your device. Only proceed if you are comfortable doing so and intend to keep these testing certificates safeguarded.

1. Navigate to the directory containing the client certificate and key.  
   1. Open the `client.pem` file in Keychain Access. If prompted, enter your local password.  
   2. In **Keychain**, choose the access option that suits your needs and select **Add**.  
   3. In the list of certificates, locate the newly installed certificate. Keychain Access will mark this certificate as not trusted. Right-click the certificate and select **Get Info**.  
   4. Select **Trust**. Under **When using this certificate**, select _Always Trust_.

Assuming your browser uses the macOS system store, you can now connect to the mTLS application through the browser.

## Generate mTLS certificates

You can use open source private key infrastructure (PKI) tools to generate certificates to test the mTLS feature in Cloudflare Access.

### OpenSSL

This section covers how to use [OpenSSL ↗](https://www.openssl.org/) to generate a root and intermediate certificate, and then issue client certificates that can authenticate against the CA chain.

#### Generate the root CA

1. Generate the root CA private key:  
Terminal window  
```  
 openssl genrsa -aes256 -out rootCA.key 4096  
```  
When prompted, enter a password to use with `rootCA.key`.
2. Create a self-signed root certificate called `rootCA.pem`:  
Terminal window  
```  
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.pem  
```  
You will be prompted to enter your private key password and fill in some optional fields. For testing purposes, you can leave the optional fields blank.

#### Generate an intermediate certificate

1. Generate the intermediate CA private key:  
Terminal window  
```  
 openssl genrsa -aes256 -out intermediate.key 4096  
```  
When prompted, enter a password to use with `intermediate.key`.
2. Create a certificate signing request (CSR) for the intermediate certificate:  
Terminal window  
```  
openssl req -new -sha256 -key intermediate.key -out intermediate.csr  
```  
You will be prompted to enter your private key password and fill in some optional fields. For testing purposes, you can leave the optional fields blank.
3. Create a CA Extension file called `v3_intermediate_ca.ext`. For example,  
```  
subjectKeyIdentifier = hash  
authorityKeyIdentifier = keyid:always,issuer  
basicConstraints = critical, CA:true  
keyUsage = critical, cRLSign, keyCertSign  
```  
Make sure that `basicConstraints` includes the `CA:true` property. This property allows the intermediate certificate to act as a CA and sign client certificates.
4. Sign the intermediate certificate with the root CA:  
Terminal window  
```  
 openssl x509 -req -in intermediate.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out intermediate.pem -days 1825 -sha256 -extfile v3_intermediate_ca.ext  
```

#### Create a CA chain file

1. Combine the intermediate and root certificates into a single file:  
Terminal window  
```  
cat intermediate.pem rootCA.pem > ca-chain.pem  
```  
The intermediate certificate should be at the top of the file, followed by its signing certificate.
2. Upload the contents of `ca-chain.pem` to Cloudflare Access. For instructions, refer to [Add mTLS to your Access application](#add-mtls-to-your-access-application).

#### Generate a client certificate

1. Generate a private key for the client:  
Terminal window  
```  
 openssl genrsa -out client.key 2048  
```
2. Create a CSR for the client certificate:  
Terminal window  
```  
openssl req -new -key client.key -out client.csr  
```  
You will be prompted to fill in some optional fields. For testing purposes, you can set **Common Name** to something like `John Doe`.
3. Sign the client certificate with the intermediate certificate:  
Terminal window  
```  
 openssl x509 -req -in client.csr -CA intermediate.pem -CAkey intermediate.key -CAcreateserial -out client.pem -days 365 -sha256  
```
4. Validate the client certificate against the certificate chain:  
Terminal window  
```  
openssl verify -CAfile ca-chain.pem client.pem  
```  
```  
client.pem: OK  
```

You can now use the client certificate (`client.pem`) and its key (`client.key`) to [test mTLS](#test-mtls).

### Cloudflare PKI

This guide uses [Cloudflare's PKI toolkit ↗](https://github.com/cloudflare/cfssl) to generate a root CA and client certificates from JSON files.

#### 1\. Install dependencies

The process requires two packages from Cloudflare's PKI toolkit:

* `cf-ssl`
* `cfssljson`

You can install these packages from the [Cloudflare SSL GitHub repository ↗](https://github.com/cloudflare/cfssl). You will need a working installation of Go, version 1.12 or later. Alternatively, you can [download the packages ↗](https://github.com/cloudflare/cfssl) directly. Use the instructions under Installation to install the toolkit, and ensure that you install all of the utility programs in the toolkit.

#### 2\. Generate the root CA

1. Create a new directory to store the root CA.
2. Within that directory, create two new files:  
   * **CSR**. Create a file named `ca-csr.json` and add the following JSON blob, then save the file.  
   ```  
   {  
     "CN": "Access Testing CA",  
     "key": {  
       "algo": "rsa",  
       "size": 4096  
     },  
     "names": [  
       {  
         "C": "US",  
         "L": "Austin",  
         "O": "Access Testing",  
         "OU": "TX",  
         "ST": "Texas"  
       }  
     ]  
   }  
   ```  
   * **config**. Create a file named `ca-config.json` and add the following JSON blob, then save the file.  
   ```  
   {  
     "signing": {  
       "default": {  
         "expiry": "8760h"  
       },  
       "profiles": {  
         "server": {  
           "usages": ["signing", "key encipherment", "server auth"],  
           "expiry": "8760h"  
         },  
         "client": {  
           "usages": ["signing", "key encipherment", "client auth"],  
           "expiry": "8760h"  
         }  
       }  
     }  
   }  
   ```
3. Now, run the following command to generate the root CA with those files.  
Terminal window  
```  
cfssl gencert -initca ca-csr.json | cfssljson -bare ca  
```
4. The command will output a root certificate (`ca.pem`) and its key (`ca-key.pem`).  
Terminal window  
```  
ls  
```  
```  
ca-config.json ca-csr.json ca-key.pem ca.csr  ca.pem  
```
5. Upload the contents of `ca.pem` to Cloudflare Access. For instructions, refer to [Add mTLS to your Access application](#add-mtls-to-your-access-application).

#### 3\. Generate a client certificate

To generate a client certificate that will authenticate against the uploaded root CA:

1. Create a file named `client-csr.json` and add the following JSON blob:  
```  
{  
  "CN": "James Royal",  
  "hosts": [""],  
  "key": {  
    "algo": "rsa",  
    "size": 4096  
  },  
  "names": [  
    {  
      "C": "US",  
      "L": "Austin",  
      "O": "Access",  
      "OU": "Access Admins",  
      "ST": "Texas"  
    }  
  ]  
}  
```
2. Now, use the following command to generate a client certificate with the Cloudflare PKI toolkit:  
Terminal window  
```  
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem  -config=ca-config.json -profile=client client-csr.json | cfssljson -bare client  
```

The command will output a client certificate file (`client.pem`) and its key (`client-key.pem`). You can now use these files to [test mTLS](#test-mtls).

#### Create a certificate revocation list

You can use the Cloudflare PKI toolkit to generate a certificate revocation list (CRL), as well. This list will contain client certificates that are revoked.

1. Get the serial number from the client certificate generated earlier. Add that serial number, or any others you intend to revoke, in hex format in a text file. This example uses a file named `serials.txt`.
2. Create the CRL with the following command.  
Terminal window  
```  
cfssl gencrl serials.txt ../mtls-test/ca.pem ../mtls-test/ca-key.pem | base64 -D > ca.crl  
```

You will need to add the CRL to your server or enforce the revocation in a Cloudflare Worker. An example Worker Script can be found on the [Cloudflare GitHub repository ↗](https://github.com/cloudflare/access-crl-worker-template).

## Add Client-Cert and Client-Cert-Chain headers (RFC 9440)

[RFC 9440 ↗](https://datatracker.ietf.org/doc/html/rfc9440) defines the `Client-Cert` and `Client-Cert-Chain` HTTP header fields for passing client certificate information to origin servers. You can construct these headers using [request header modification rules](https://developers.cloudflare.com/rules/transform/request-header-modification/) with the following Ruleset Engine fields:

* [cf.tls\_client\_auth.cert\_rfc9440](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Frfc9440/) — The client leaf certificate encoded in RFC 9440 formatting (see reference).
* [cf.tls\_client\_auth.cert\_chain\_rfc9440](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fchain%5Frfc9440/) — The certificate chain (excluding the leaf certificate) encoded in RFC 9440 formatting (see reference).

As indicated in field definitions, the fields may be set to either an empty string or a valid RFC 9440 encoding. Proper usage depends on a couple of factors discussed in the following sections.

### Security considerations

Important

Before constructing `Client-Cert` or `Client-Cert-Chain` headers, you must address the following security concerns. Failing to do so can expose your origin server to forged or unverified certificate data.

The `cert_rfc9440` and `cert_chain_rfc9440` fields are populated **regardless of the certificate validation result**. This means a client can present an invalid, expired, or self-signed certificate, and the fields will still contain the encoded certificate data. Always check the following fields before trusting the values:

* [cf.tls\_client\_auth.cert\_verified](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fverified/) — Returns `true` when the client certificate is valid.
* [cf.tls\_client\_auth.cert\_revoked](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Frevoked/) — Returns `true` when the client certificate has been revoked.

A client can also include its own `Client-Cert` or `Client-Cert-Chain` headers on a request to inject arbitrary values. As described in the [RFC 9440 security considerations ↗](https://datatracker.ietf.org/doc/html/rfc9440#name-security-considerations), you must unconditionally remove any existing `Client-Cert` and `Client-Cert-Chain` headers from incoming requests, regardless of certificate validity. This prevents a client from injecting forged certificate data that your origin would trust.

See [Enable mTLS](https://developers.cloudflare.com/ssl/client-certificates/enable-mtls/) for details on how to configure mTLS and certificate validation.

### Size limits

The encoded leaf certificate is limited to 10 KiB and the encoded chain is limited to 16 KiB. If the encoded value exceeds the limit, the corresponding field contains an empty string. Use the following fields to check for this condition:

* [cf.tls\_client\_auth.cert\_rfc9440\_too\_large](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Frfc9440%5Ftoo%5Flarge/) — Returns `true` when the encoded certificate exceeds 10 KiB.
* [cf.tls\_client\_auth.cert\_chain\_rfc9440\_too\_large](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls%5Fclient%5Fauth.cert%5Fchain%5Frfc9440%5Ftoo%5Flarge/) — Returns `true` when the encoded chain exceeds 16 KiB.

### Example Transform Rules

Here we provide an example on how to securely use these fields to construct trusted `Client-Cert` and `Client-Cert-Chain` headers to be forwarded to your origin. The origin can then rely on the presence of the headers to be certain the client presented a valid certificate. Note: the `Client-Cert-Chain` header may be omitted when the client did not present any intermediates (only a leaf certificate).

You need to create the following request header modification rules. The **Remove** rules must be placed before the **Set dynamic** rules so that client-injected headers are stripped on every request before the validated values are set.

#### Rule 1 — Remove Client-Cert header

This rule unconditionally removes any `Client-Cert` header sent by the client.

Text in **Expression Editor**:

```

true


```

Selected operation under **Modify request header**: _Remove_

**Header name**: `Client-Cert`

#### Rule 2 — Remove Client-Cert-Chain header

This rule unconditionally removes any `Client-Cert-Chain` header sent by the client.

Text in **Expression Editor**:

```

true


```

Selected operation under **Modify request header**: _Remove_

**Header name**: `Client-Cert-Chain`

#### Rule 3 — Set Client-Cert header

This rule sets the `Client-Cert` header only when the client presented a valid, non-revoked certificate that is within the size limit.

Text in **Expression Editor**:

```

cf.tls_client_auth.cert_verified

and not cf.tls_client_auth.cert_revoked

and not cf.tls_client_auth.cert_rfc9440_too_large


```

Selected operation under **Modify request header**: _Set dynamic_

**Header name**: `Client-Cert`

**Value**: `cf.tls_client_auth.cert_rfc9440`

#### Rule 4 — Set Client-Cert-Chain header

This rule sets the `Client-Cert-Chain` header only when the client presented a valid, non-revoked certificate and the chain is non-empty and within the size limit.

Text in **Expression Editor**:

```

cf.tls_client_auth.cert_verified

and not cf.tls_client_auth.cert_revoked

and cf.tls_client_auth.cert_chain_rfc9440 ne ""

and not cf.tls_client_auth.cert_chain_rfc9440_too_large


```

Selected operation under **Modify request header**: _Set dynamic_

**Header name**: `Client-Cert-Chain`

**Value**: `cf.tls_client_auth.cert_chain_rfc9440`

### Cloudflare Workers

You can also construct RFC 9440 headers in a [Cloudflare Worker](https://developers.cloudflare.com/workers/)using the [tlsClientAuth](https://developers.cloudflare.com/ssl/client-certificates/client-certificate-variables/#workers-variables)properties on the incoming request.

The same security considerations mentioned above apply.

## Forward a client certificate (legacy)

In addition to enforcing mTLS authentication for your host, you can also forward a client certificate to your origin server as an HTTP header. This setup is often helpful for server logging.

To avoid adding the certificate to every single request, the certificate is only forwarded on the first request of an mTLS connection.

Warning

This process is only available on accounts with [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/).

### Cloudflare API

The most common approach to forwarding a certificate is to use the Cloudflare API to [update an mTLS certificate's hostname settings](https://developers.cloudflare.com/api/resources/zero%5Ftrust/subresources/access/subresources/certificates/subresources/settings/methods/update/).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Access: Mutual TLS Certificates Write`

Update an mTLS certificate's hostname settings

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/access/certificates/settings" \

  --request PUT \

  --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \

  --header "X-Auth-Key: $CLOUDFLARE_API_KEY" \

  --json '{

    "settings": [

        {

            "hostname": "<HOSTNAME>",

            "china_network": false,

            "client_certificate_forwarding": true

        }

    ]

  }'


```

Once `client_certificate_forwarding` is set to `true`, every request within an mTLS connection will now include the following headers:

* `Cf-Client-Cert-Der-Base64`
* `Cf-Client-Cert-Sha256`

Note

The `Cf-Client-Cert-Der-Base64` and `Cf-Client-Cert-Sha256` headers are a Cloudflare-proprietary mechanism. For a standardized approach, use [RFC 9440 Client-Cert and Client-Cert-Chain headers](https://developers.cloudflare.com/ssl/client-certificates/forward-a-client-certificate/#add-client-cert-and-client-cert-chain-headers-rfc-9440).

### Managed Transforms

You can also [modify HTTP response headers](https://developers.cloudflare.com/rules/transform/response-header-modification/) using Managed Transforms to pass along **TLS client auth headers**.

### Cloudflare Workers

Additionally, Workers can provide details around the [client certificate](https://developers.cloudflare.com/workers/runtime-apis/bindings/mtls/).

JavaScript

```

const tlsHeaders = {

  "X-CERT-ISSUER-DN": request.cf.tlsClientAuth.certIssuerDN,

  "X-CERT-SUBJECT-DN": request.cf.tlsClientAuth.certSubjectDN,

  "X-CERT-ISSUER-DN-L": request.cf.tlsClientAuth.certIssuerDNLegacy,

  "X-CERT-SUBJECT-DN-L": request.cf.tlsClientAuth.certSubjectDNLegacy,

  "X-CERT-SERIAL": request.cf.tlsClientAuth.certSerial,

  "X-CERT-FINGER": request.cf.tlsClientAuth.certFingerprintSHA1,

  "X-CERT-VERIFY": request.cf.tlsClientAuth.certVerify,

  "X-CERT-NOTBE": request.cf.tlsClientAuth.certNotBefore,

  "X-CERT-NOTAF": request.cf.tlsClientAuth.certNotAfter,

};


```

## Known limitations

mTLS does not currently work for:

* Cloudflare Pages site served on a [custom domain](https://developers.cloudflare.com/pages/configuration/custom-domains/)
* Cloudflare R2 public bucket served on a [custom domain](https://developers.cloudflare.com/r2/buckets/public-buckets/#connect-a-bucket-to-a-custom-domain)

## Notifications for mutual TLS certificates

Cloudflare will send the following [notifications](https://developers.cloudflare.com/notifications/) before your mutual TLS certificates expire:

Access mTLS Certificate Expiration Alert

**Who is it for?**

[Access](https://developers.cloudflare.com/cloudflare-one/access-controls/policies/) customers that use client certificates for mutual TLS authentication. This notification will be sent 30 and 14 days before the expiration of the certificate.

**Other options / filters**

None.

**Included with**

Purchase of [Access](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/mutual-tls-authentication/) and/or [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/).

**What should you do if you receive one?**

Upload a [renewed certificate](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/mutual-tls-authentication/#add-mtls-authentication-to-your-access-configuration).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-one/","name":"Cloudflare One"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-one/access-controls/","name":"Access controls"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-one/access-controls/service-credentials/","name":"Service credentials"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-one/access-controls/service-credentials/mutual-tls-authentication/","name":"Mutual TLS"}}]}
```

---

---
title: Cloudflare for SaaS
description: Extend Cloudflare security and performance to your customers' custom hostnames.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare for SaaS

Cloudflare for SaaS allows you to extend the security and performance benefits of Cloudflare's network to your customers via their own custom or vanity domains.

  
As a SaaS provider, you may want to support subdomains under your own zone in addition to letting your customers use their own domain names with your services. For example, a customer may want to use their vanity domain `app.customer.com` to point to an application hosted on your Cloudflare zone `service.saas.com`. Cloudflare for SaaS allows you to increase security, performance, and reliability of your customers' domains.

Note

Eligible enterprise customers can preview this product as a [non-contract service](https://developers.cloudflare.com/billing/understand/preview-services/), which provides full access, free of metered usage fees, limits, and certain other restrictions.

## Benefits

When you use Cloudflare for SaaS, it helps you to:

* Provide custom domain support.
* Keep your customers' traffic encrypted.
* Keep your customers online.
* Facilitate fast load times of your customers' domains.
* Gain insight through traffic analytics.

## Limitations

If your customers already have their applications on Cloudflare, they cannot control some Cloudflare features for hostnames managed by your Custom Hostnames configuration, including:

* Argo
* Early Hints
* Client-side security (formerly known as Page Shield)
* Spectrum
* Wildcard DNS

## How it works

As the SaaS provider, you can extend Cloudflare's products to customer-owned custom domains by adding them to your zone [as custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/). Through a suite of easy-to-use products, Cloudflare for SaaS routes traffic from custom hostnames to an origin, set up on your domain. Cloudflare for SaaS is highly customizable. Three possible configurations are shown below.

### Standard Cloudflare for SaaS configuration:

Custom hostnames are routed to a default origin server called fallback origin. This configuration is available on all plans.

![Standard case](https://developers.cloudflare.com/_astro/Standard.DlPYrpsG_Z1aQodp.webp) 

### Cloudflare for SaaS with Apex Proxying:

This allows you to support apex domains even if your customers are using a DNS provider that does not allow a CNAME at the apex. This is available as an add-on for Enterprise plans. For more details, refer to [Apex Proxying](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/).

![Advanced case](https://developers.cloudflare.com/_astro/Advanced.BaQXgT8v_Z1DP3hz.webp) 

### Cloudflare for SaaS with BYOIP:

This allows you to support apex domains even if your customers are using a DNS provider that does not allow a CNAME at the apex. Also, you can point to your own IPs if you want to bring an IP range to Cloudflare (instead of Cloudflare provided IPs). This is available as an add-on for Enterprise plans.

![Pro Case](https://developers.cloudflare.com/_astro/Pro.DTAC_nZK_Z23M1FF.webp) 

## Availability

Cloudflare for SaaS is bundled with non-Enterprise plans and available as an add-on for Enterprise plans. For more details, refer to [Plans](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/plans/).

## Next steps

[ Get started ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/) [ Learn more ](https://blog.cloudflare.com/introducing-ssl-for-saas/) 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}}]}
```

---

---
title: Keyless SSL
description: Keep private keys on your own infrastructure while using Cloudflare TLS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Keyless SSL

Keyless SSL allows security-conscious clients to upload their own custom certificates and benefit from Cloudflare, but without exposing their TLS private keys.

  
Before configuring Keyless SSL, you should read our [technical background ↗](https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/) on how the technology works and where your infrastructure sits within the scope of the TLS handshake.

The source code for our key server (what you will run) and keyless client (what our servers will contact your key server with) can be [found on GitHub ↗](https://github.com/cloudflare/gokeyless).

---

## Availability

| Free         | Pro | Business | Enterprise |             |
| ------------ | --- | -------- | ---------- | ----------- |
| Availability | No  | No       | No         | Paid add-on |

Keyless SSL is only available to Enterprise customers that maintain their own SSL certificate purchased from a valid Certificate Authority. Cloudflare does not supply any certificates for use with Keyless SSL.

---

## Limitations

TLS 1.3 is not supported for Keyless SSL.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}}]}
```

---

---
title: Cloudflare Tunnel
description: Deploy Keyless SSL with Cloudflare Tunnel for private connectivity.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare Tunnel

Through an integration with [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/), you can send traffic to a key server through a secure channel and avoid exposing your key server to the public Internet.

---

## Before you begin

### Supported platforms

Keyless has been tested on `amd64` and `arm` architectures. The key server binary will likely run on all architectures that Go supports. Code support may exist for other CPUs too, but these other architectures have not been tested.

In addition to running on bare metal, the key server should run without issue in a virtualized or containerized environment. Care will need to be taken to configure ingress access to the appropriate TCP port and file system access to private keys (if using filesystem storage).

### Supported operating systems

You will need to have a supported operating system (OS) to run Keyless. Supported operating systems include:

* Ubuntu 20.04 LTS (Focal), 22.04 LTS (Jammy), 24.04 LTS (Noble)
* Debian 11 (Bullseye), 12 (Bookworm), 13 (Trixie)
* RHEL 8, 9, CentOS 8, and CentOS Stream 9
* Amazon Linux 2, 2023

We strongly recommend that you use an operating system still supported by the vendor (still receiving security updates) as your key server will have access to your private keys.

---

## 1\. Install `cloudflared` on key server

First, install `cloudflared` on your key server.

This process differs depending on whether you are using the [command line](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/local-management/create-local-tunnel/) or the [Cloudflare dashboard](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/get-started/create-remote-tunnel/).

## 2\. Create a tunnel and add a route

Then, create a Cloudflare Tunnel.

This process differs depending on whether you are using the [command line](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/local-management/create-local-tunnel/) or the [Cloudflare dashboard](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/get-started/create-remote-tunnel/).

During tunnel creation, go to the **CIDR** tab and enter the private IP address of your key server. You can also [add a CIDR route](https://developers.cloudflare.com/cloudflare-one/networks/routes/add-routes/#add-a-cidr-route) after creating the tunnel.

After you create the tunnel, use the Cloudflare API to [List tunnel routes](https://developers.cloudflare.com/api/resources/zero%5Ftrust/subresources/networks/subresources/routes/methods/list/), saving the following values for a future step:

* `"virtual_network_id"`
* `"network"`

## 3\. Upload Keyless SSL Certificates

Before your key servers can be configured, you must next upload the corresponding SSL certificates to Cloudflare’s edge. During TLS termination, Cloudflare will present these certificates to connecting browsers and then (for non-resumed sessions) communicate with the specified key server to complete the handshake.

Upload certificates to Cloudflare with only SANs that you wish to use with Cloudflare Keyless SSL. All Keyless SSL hostnames must be [proxied](https://developers.cloudflare.com/dns/proxy-status/).

You will have to upload each certificate used with Keyless SSL.

To upload a Keyless certificate with the API, send a [POST](https://developers.cloudflare.com/api/resources/keyless%5Fcertificates/methods/create/) request that includes a `"tunnel"` object.

```

"tunnel": {

  "vnet_id": "<VIRTUAL_NETWORK_ID>",

  "private_ip": "<NETWORK>"

}


```

Note

When you receive the `network` value from the Tunnel route API, it will include a subnet mask, such as `10.0.0.1/32`. Remove the subnet mask and use the IP address (`10.0.0.1`).

## 4\. Set up and activate key server

Finally, you need to install the key server on your infrastructure, populate it with the SSL keys of the certificates you wish to use to terminate TLS at Cloudflare’s edge, and activate the key server so it can be mutually authenticated.

Note

If you plan to run Keyless SSL in a [high availability setup](https://developers.cloudflare.com/ssl/keyless-ssl/reference/high-availability/), you may need to set up additional infrastructure (load balancing and health checks).

### Install

These steps are also at the [Cloudflare package repository ↗](https://pkg.cloudflare.com/).

#### Debian/Ubuntu packages

* [ Debian 13 (Trixie) ](#tab-panel-10469)
* [ Debian 12 (Bookworm) ](#tab-panel-10470)
* [ Debian 11 (Bullseye) ](#tab-panel-10471)
* [ Ubuntu 24.04 (Noble) ](#tab-panel-10472)
* [ Ubuntu 22.04 (Jammy) ](#tab-panel-10473)
* [ Ubuntu 20.04 (Focal) ](#tab-panel-10474)

Terminal window

```

sudo mkdir -p --mode=0755 /usr/share/keyrings

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null


echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/gokeyless trixie main' | sudo tee /etc/apt/sources.list.d/cloudflare.list


sudo apt-get update && sudo apt-get install gokeyless


```

Terminal window

```

sudo mkdir -p --mode=0755 /usr/share/keyrings

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null


echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/gokeyless bookworm main' | sudo tee /etc/apt/sources.list.d/cloudflare.list


sudo apt-get update && sudo apt-get install gokeyless


```

Terminal window

```

sudo mkdir -p --mode=0755 /usr/share/keyrings

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null


echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/gokeyless bullseye main' | sudo tee /etc/apt/sources.list.d/cloudflare.list


sudo apt-get update && sudo apt-get install gokeyless


```

Terminal window

```

sudo mkdir -p --mode=0755 /usr/share/keyrings

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null


echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/gokeyless noble main' | sudo tee /etc/apt/sources.list.d/cloudflare.list


sudo apt-get update && sudo apt-get install gokeyless


```

Terminal window

```

sudo mkdir -p --mode=0755 /usr/share/keyrings

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null


echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/gokeyless jammy main' | sudo tee /etc/apt/sources.list.d/cloudflare.list


sudo apt-get update && sudo apt-get install gokeyless


```

Terminal window

```

sudo mkdir -p --mode=0755 /usr/share/keyrings

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null


echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/gokeyless focal main' | sudo tee /etc/apt/sources.list.d/cloudflare.list


sudo apt-get update && sudo apt-get install gokeyless


```

#### RHEL/CentOS/Amazon Linux packages

Gokeyless uses CGO for PKCS#11/HSM support, which creates glibc dependencies. Use the repository that matches your distribution.

* [ RHEL 9 / CentOS Stream 9 ](#tab-panel-10475)
* [ Amazon Linux 2023 ](#tab-panel-10476)
* [ RHEL 8 / CentOS 8 ](#tab-panel-10477)
* [ Amazon Linux 2 ](#tab-panel-10478)

Terminal window

```

sudo dnf config-manager --add-repo https://pkg.cloudflare.com/gokeyless/rpm/gokeyless.repo

sudo dnf install gokeyless


```

Terminal window

```

curl -fsSl https://pkg.cloudflare.com/gokeyless/rpm/gokeyless.repo | sudo tee /etc/yum.repos.d/gokeyless.repo

sudo yum update

sudo yum install gokeyless


```

Terminal window

```

sudo dnf config-manager --add-repo https://pkg.cloudflare.com/gokeyless/rpm-el8/gokeyless.repo

sudo dnf install gokeyless


```

Terminal window

```

curl -fsSl https://pkg.cloudflare.com/gokeyless/rpm-el8/gokeyless.repo | sudo tee /etc/yum.repos.d/gokeyless.repo

sudo yum update

sudo yum install gokeyless


```

### Configure

Add your Cloudflare account details to the configuration file located at `/etc/keyless/gokeyless.yaml`:

1. Set the hostname of the key server, for example, `keyserver.keyless.example.com`. This is also the value you entered when you uploaded your keyless certificate and is the hostname of your key server that holds the key for this certificate.
2. Set the Zone ID (found on **Overview** tab of the Cloudflare dashboard).
3. [Set the Origin CA API key](https://developers.cloudflare.com/fundamentals/api/get-started/ca-keys).

### Populate keys

Install your private keys in `/etc/keyless/keys/` and set the user and group to keyless with 400 permissions. Keys must be in PEM or DER format and have an extension of `.key`:

Terminal window

```

ls -l /etc/keyless/keys


```

```

-r-------- 1 keyless keyless 1675 Nov 18 16:44 example.com.key


```

When running multiple key servers, make sure all required keys are distributed to each key server. Customers typically will either use a configuration management tool such as Salt or Puppet to distribute keys or mount `/etc/keyless/keys` to a network location accessible only by your key servers. Keys are read on boot into memory, so a network path must be accessible during the gokeyless process start/restart.

### Activate

To activate, restart your keyless instance:

* systemd: `sudo service gokeyless restart`
* upstart/sysvinit: `sudo /etc/init.d/gokeyless restart`

If this command fails, try troubleshooting by [checking the logs](https://developers.cloudflare.com/ssl/keyless-ssl/troubleshooting/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/configuration/","name":"Get started"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/configuration/cloudflare-tunnel/","name":"Cloudflare Tunnel"}}]}
```

---

---
title: Public DNS
description: Deploy Keyless SSL with public DNS resolution.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Public DNS

If you cannot use a [Cloudflare Tunnel setup](https://developers.cloudflare.com/ssl/keyless-ssl/configuration/cloudflare-tunnel/), you can also create a public DNS record for your key server.

This setup option is not ideal as the DNS record cannot be [proxied](https://developers.cloudflare.com/dns/proxy-status/) and - as a result - will expose the origin IP address of your key server.

---

## Before you begin

### Supported platforms

Keyless has been tested on `amd64` and `arm` architectures. The key server binary will likely run on all architectures that Go supports. Code support may exist for other CPUs too, but these other architectures have not been tested.

In addition to running on bare metal, the key server should run without issue in a virtualized or containerized environment. Care will need to be taken to configure ingress access to the appropriate TCP port and file system access to private keys (if using filesystem storage).

### Supported operating systems

You will need to have a supported operating system (OS) to run Keyless. Supported operating systems include:

* Ubuntu 20.04 LTS (Focal), 22.04 LTS (Jammy), 24.04 LTS (Noble)
* Debian 11 (Bullseye), 12 (Bookworm), 13 (Trixie)
* RHEL 8, 9, CentOS 8, and CentOS Stream 9
* Amazon Linux 2, 2023

We strongly recommend that you use an operating system still supported by the vendor (still receiving security updates) as your key server will have access to your private keys.

---

## 1\. Create public DNS record

1. Open a Terminal and run `openssl rand -hex 24` to generate a long, random hostname such as `11aa40b4a5db06d4889e48e2f738950ddfa50b7349d09b5f.example.com`.
2. Add this record via your DNS provider’s interface as an **A** or **AAAA** record pointing to the IP address of your Keyless SSL server.
3. Use this hostname as the server hostname during initialization of your Keyless SSL server.

Warning

As a security measure, you should hide the hostname of your key server.

---

## 2\. Upload Keyless SSL Certificates

Before your key servers can be configured, you must next upload the corresponding SSL certificates to Cloudflare’s edge. During TLS termination, Cloudflare will present these certificates to connecting browsers and then (for non-resumed sessions) communicate with the specified key server to complete the handshake.

Upload certificates to Cloudflare with only SANs that you wish to use with Cloudflare Keyless SSL. All Keyless SSL hostnames must be [proxied](https://developers.cloudflare.com/dns/proxy-status/).

You will have to upload each certificate used with Keyless SSL.

* [ Dashboard ](#tab-panel-10479)
* [ API ](#tab-panel-10480)

To create a Keyless certificate in the dashboard:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. Select **Upload Keyless SSL Certificate**.
3. Fill in the upload modal with the certificate and other details and select **Add**.

| Label               | Description                                                                                                                                                                                     | Example Values                                               |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| Key server label    | Any unique identifier for your key server.                                                                                                                                                      | “test-keyless”, “production-keyless-1”                       |
| Key server hostname | The hostname of your key server that holds the key for this certificate (such as the random hostname generated earlier).                                                                        | 11aa40b4a5db06d4889e48e2f738950ddfa50b7349d09b5f.example.com |
| Key server port     | Set to 2407 unless you have changed this on the key server.                                                                                                                                     | 2407                                                         |
| SSL Certificate     | The valid X509v3 SSL certificate (in PEM form) for which you hold the private key.                                                                                                              | (PEM bytes)                                                  |
| Bundle method       | This should almost always be **Compatible**. Refer to [Uploading Custom Certificates](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/) for more details. | Compatible                                                   |

To create a Keyless certificate with the API, send a [POST](https://developers.cloudflare.com/api/resources/keyless%5Fcertificates/methods/create/) request.

---

## 3\. Set up and activate key server

Finally, you need to install the key server on your infrastructure, populate it with the SSL keys of the certificates you wish to use to terminate TLS at Cloudflare’s edge, and activate the key server so it can be mutually authenticated.

Note

If you plan to run Keyless SSL in a [high availability setup](https://developers.cloudflare.com/ssl/keyless-ssl/reference/high-availability/), you may need to set up additional infrastructure (load balancing and health checks).

### Install

These steps are also at the [Cloudflare package repository ↗](https://pkg.cloudflare.com/).

#### Debian/Ubuntu packages

* [ Debian 13 (Trixie) ](#tab-panel-10481)
* [ Debian 12 (Bookworm) ](#tab-panel-10482)
* [ Debian 11 (Bullseye) ](#tab-panel-10483)
* [ Ubuntu 24.04 (Noble) ](#tab-panel-10484)
* [ Ubuntu 22.04 (Jammy) ](#tab-panel-10485)
* [ Ubuntu 20.04 (Focal) ](#tab-panel-10486)

Terminal window

```

sudo mkdir -p --mode=0755 /usr/share/keyrings

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null


echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/gokeyless trixie main' | sudo tee /etc/apt/sources.list.d/cloudflare.list


sudo apt-get update && sudo apt-get install gokeyless


```

Terminal window

```

sudo mkdir -p --mode=0755 /usr/share/keyrings

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null


echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/gokeyless bookworm main' | sudo tee /etc/apt/sources.list.d/cloudflare.list


sudo apt-get update && sudo apt-get install gokeyless


```

Terminal window

```

sudo mkdir -p --mode=0755 /usr/share/keyrings

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null


echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/gokeyless bullseye main' | sudo tee /etc/apt/sources.list.d/cloudflare.list


sudo apt-get update && sudo apt-get install gokeyless


```

Terminal window

```

sudo mkdir -p --mode=0755 /usr/share/keyrings

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null


echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/gokeyless noble main' | sudo tee /etc/apt/sources.list.d/cloudflare.list


sudo apt-get update && sudo apt-get install gokeyless


```

Terminal window

```

sudo mkdir -p --mode=0755 /usr/share/keyrings

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null


echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/gokeyless jammy main' | sudo tee /etc/apt/sources.list.d/cloudflare.list


sudo apt-get update && sudo apt-get install gokeyless


```

Terminal window

```

sudo mkdir -p --mode=0755 /usr/share/keyrings

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null


echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/gokeyless focal main' | sudo tee /etc/apt/sources.list.d/cloudflare.list


sudo apt-get update && sudo apt-get install gokeyless


```

#### RHEL/CentOS/Amazon Linux packages

Gokeyless uses CGO for PKCS#11/HSM support, which creates glibc dependencies. Use the repository that matches your distribution.

* [ RHEL 9 / CentOS Stream 9 ](#tab-panel-10487)
* [ Amazon Linux 2023 ](#tab-panel-10488)
* [ RHEL 8 / CentOS 8 ](#tab-panel-10489)
* [ Amazon Linux 2 ](#tab-panel-10490)

Terminal window

```

sudo dnf config-manager --add-repo https://pkg.cloudflare.com/gokeyless/rpm/gokeyless.repo

sudo dnf install gokeyless


```

Terminal window

```

curl -fsSl https://pkg.cloudflare.com/gokeyless/rpm/gokeyless.repo | sudo tee /etc/yum.repos.d/gokeyless.repo

sudo yum update

sudo yum install gokeyless


```

Terminal window

```

sudo dnf config-manager --add-repo https://pkg.cloudflare.com/gokeyless/rpm-el8/gokeyless.repo

sudo dnf install gokeyless


```

Terminal window

```

curl -fsSl https://pkg.cloudflare.com/gokeyless/rpm-el8/gokeyless.repo | sudo tee /etc/yum.repos.d/gokeyless.repo

sudo yum update

sudo yum install gokeyless


```

### Configure

Add your Cloudflare account details to the configuration file located at `/etc/keyless/gokeyless.yaml`:

1. Set the hostname of the key server, for example, `11aa40b4a5db06d4889e48e2f.example.com`. This is also the value you entered when you uploaded your keyless certificate and is the hostname of your key server that holds the key for this certificate.
2. Set the Zone ID (found on **Overview** tab of the Cloudflare dashboard).
3. [Set the Origin CA API key](https://developers.cloudflare.com/fundamentals/api/get-started/ca-keys).

### Populate keys

Install your private keys in `/etc/keyless/keys/` and set the user and group to keyless with 400 permissions. Keys must be in PEM or DER format and have an extension of `.key`:

Terminal window

```

ls -l /etc/keyless/keys


```

```

-r-------- 1 keyless keyless 1675 Nov 18 16:44 example.com.key


```

When running multiple key servers, make sure all required keys are distributed to each key server. Customers typically will either use a configuration management tool such as Salt or Puppet to distribute keys or mount `/etc/keyless/keys` to a network location accessible only by your key servers. Keys are read on boot into memory, so a network path must be accessible during the gokeyless process start/restart.

### Activate

To activate, restart your keyless instance:

* systemd: `sudo service gokeyless restart`
* upstart/sysvinit: `sudo /etc/init.d/gokeyless restart`

If this command fails, try troubleshooting by [checking the logs](https://developers.cloudflare.com/ssl/keyless-ssl/troubleshooting/).

### Allow incoming connections from Cloudflare

During TLS handshakes, Cloudflare's keyless client will initiate connections to the key server hostname or IP address you specify during certificate upload. By default, the keyless client will use a destination TCP port of 2407, but this can be changed during certificate upload or by editing the certificate details after upload.

Create WAF custom rules that allow your key server to accept connections from only Cloudflare. You can get Cloudflare's IPv4 and IPv6 addresses via the [IP details API endpoint](https://developers.cloudflare.com/api/resources/ips/methods/list/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/configuration/","name":"Get started"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/configuration/public-dns/","name":"Public DNS"}}]}
```

---

---
title: Glossary
description: Learn more about the common terms related to Keyless SSL.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Glossary

## Cloudflare Keyless SSL key server (“key server”)

The key server is a daemon that you run on your own infrastructure. The key server receives inbound requests from Cloudflare's keyless client on TCP port `2407` (by default) so you must make sure that your firewall and other access control lists permit these requests from [Cloudflare's IP ranges ↗](https://www.cloudflare.com/ips/).

Your key servers are contacted by Cloudflare during the TLS handshake process and must be online to terminate new TLS connections. Existing sessions can be resumed using unexpired TLS session tickets without needing to contact the key server.

## Cloudflare Keyless SSL client (“keyless client”)

The keyless client is a process that runs on Cloudflare's infrastructure. The keyless client makes outbound requests to your key server on TCP port `2407` for assistance in establishing new TLS sessions.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/glossary/","name":"Glossary"}}]}
```

---

---
title: Hardware security modules
description: Store private keys in hardware security modules for Keyless SSL.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Hardware security modules

In addition to private keys stored on disk, Keyless SSL supports keys stored in a Hardware Security Module (HSM) via the PKCS#11 standard. Keyless uses PKCS#11 for signing and decrypting payloads without having direct access to the private keys.

---

## Why use Keyless SSL with an HSM?

Hardware Security Modules (HSMs) facilitate a higher level of protection for your private keys over storing them directly on your key server. The primary responsibility of an HSM is safeguarding private keys and performing operations such as signing or encryption internally. In addition to access control, that means the physical device must offer some degree of tamper-resistance in order to be compliant with government or [industry regulations such as FIPS 140 ↗](https://csrc.nist.gov/pubs/fips/140-3/final).

Moreover, many HSMs are also capable of generating keys and producing cryptographically secure randomness. Some are purpose-built to perform cryptographic computations more efficiently.

---

## Communicating using PKCS#11

The key server communicates with HSMs via PKCS#11, so any HSM supporting the standard can be used with Keyless SSL.

### Initial configuration

For more details on initializing your PKCS#11 token, refer to [Configuration](https://developers.cloudflare.com/ssl/keyless-ssl/hardware-security-modules/configuration/).

### Compatibility

Keyless SSL has interoperability with the following modules:

* [Entrust nShield Connect ↗](https://www.entrust.com/digital-security/hsm)
* [Gemalto SafeNet Luna ↗](https://cpl.thalesgroup.com/compliance/fips-common-criteria-validations)
* [SoftHSMv2 ↗](https://github.com/opendnssec/SoftHSMv2)
* [YubiKey Neo ↗](https://www.yubico.com/product/yubikey-neo/)

Also, the following cloud HSM offerings have been tested with Keyless SSL:

* [AWS CloudHSM](https://developers.cloudflare.com/ssl/keyless-ssl/hardware-security-modules/aws-cloud-hsm/)
* [Azure Dedicated HSM](https://developers.cloudflare.com/ssl/keyless-ssl/hardware-security-modules/azure-dedicated-hsm/)
* [Azure Managed HSM](https://developers.cloudflare.com/ssl/keyless-ssl/hardware-security-modules/azure-managed-hsm/)
* [Fortanix DSM](https://developers.cloudflare.com/ssl/keyless-ssl/hardware-security-modules/fortanix-dsm/)
* [IBM Cloud HSM](https://developers.cloudflare.com/ssl/keyless-ssl/hardware-security-modules/ibm-cloud-hsm/)
* [Google Cloud HSM](https://developers.cloudflare.com/ssl/keyless-ssl/hardware-security-modules/google-cloud-hsm/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/","name":"Hardware security modules"}}]}
```

---

---
title: AWS cloud HSM
description: Learn how to use Keyless SSL with AWS CloudHSM.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# AWS cloud HSM

Note

This example imports an existing key pair, but you may prefer to [generate your key on the HSM ↗](https://docs.aws.amazon.com/cloudhsm/latest/userguide/manage-keys.html).

---

## Before you start

Make sure you have:

* Provisioned an [AWS CloudHSM cluster ↗](https://docs.aws.amazon.com/cloudhsm/latest/userguide/getting-started.html) .
* Installed the [appropriate software library for PKCS#11 ↗](https://docs.aws.amazon.com/cloudhsm/latest/userguide/pkcs11-library-install.html).

---

## 1\. Import the public and private key to the HSM

Before importing the public key, extract it from the certificate provided by your CA. Place the contents of your private key in `privkey.pem` and then run the following (replacing certificate.pem with your actual certificate) to populate `pubkey.pm`.

```

keyserver$ openssl x509 -pubkey -noout -in certificate.pem > pubkey.pem


```

Log in to the CloudHSM using a previously created [crypto user ↗](https://docs.aws.amazon.com/cloudhsm/latest/userguide/hsm-users.html#crypto-user) (CU) account and generate a key encryption key that will be used to import your private key.

```

keyserver$ /opt/cloudhsm/bin/key_mgmt_util

Command: loginHSM -u CU -s patrick -p donahue

Command: genSymKey -t 31 -s 16 -sess -l import-wrapping-key

...

Symmetric Key Created.  Key Handle: 658

...


```

Referencing the key handle returned above, import the private and public key and then log out of the HSM:

```

Command: importPrivateKey -f privkey.pem -l mykey -id 1 -w 658

...

Cfm3WrapHostKey returned: 0x00 : HSM Return: SUCCESS

Cfm3CreateUnwrapTemplate returned: 0x00 : HSM Return: SUCCESS

Cfm3UnWrapKey returned: 0x00 : HSM Return: SUCCESS

...

Private Key Unwrapped.  Key Handle: 658


Command: importPubKey -f pubkey.pem -l mykey -id 1

Cfm3CreatePublicKey returned: 0x00 : HSM Return: SUCCESS

...

Public Key Handle: 941


Command: logoutHSM

Command: exit


```

---

## 2\. Modify the gokeyless config file and restart the service

Now that the keys are in place, we need to modify the configuration file that the key server will read on startup. Change the `object=mykey` and `pin-value=username:password` values to match the key label you provided and CU user you created.

Open `/etc/keyless/gokeyless.yaml` and immediately after:

YAML

```

private_key_stores:

  - dir: /etc/keyless/keys


```

add:

YAML

```

- uri: pkcs11:token=cavium;object=mykey?module-path=/opt/cloudhsm/lib/libcloudhsm_pkcs11_standard.so&pin-value=patrick:donahue&max-sessions=1


```

With the config file saved, restart `gokeyless` and verify it started successfully.

Terminal window

```

sudo systemctl restart gokeyless.service

sudo systemctl status gokeyless.service -l


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/","name":"Hardware security modules"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/aws-cloud-hsm/","name":"AWS cloud HSM"}}]}
```

---

---
title: Azure Dedicated HSM
description: Learn how to use Keyless SSL with Azure Dedicated HSM.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Azure Dedicated HSM

This tutorial uses [Azure Dedicated HSM ↗](https://azure.microsoft.com/en-us/services/azure-dedicated-hsm/) — a FIPS 140-2 Level 3 certified implementation based on the Gemalto SafeNet Luna a790.

---

## Before you start

Make sure you have:

* Followed Microsoft's [tutorial ↗](https://docs.microsoft.com/en-us/azure/dedicated-hsm/tutorial-deploy-hsm-powershell) for deploying HSMs into an existing virtual network using PowerShell
* Installed the [SafeNet client software ↗](https://cpl.thalesgroup.com/node/11350)

---

## 1\. Create, assign, and initialize a new partition

The first step is creating an HSM partition, which can be thought of as an independent logical HSM within your Azure Dedicated HSM device.

```

vm$ ssh tenantadmin@hsm


[local_host] lunash:>hsm login

  Please enter the HSM Administrators' password:

  > ********


'hsm login' successful.


Command Result : 0 (Success)


[local_host] lunash:>partition create -partition KeylessSSL


          Type 'proceed' to create the partition, or

          'quit' to quit now.

          > proceed

'partition create' successful.


Command Result : 0 (Success)


```

Next, the partition needs to be assigned to the client, in this case your key server.

Terminal window

```

[local_host] lunash:>client assignpartition -client azure-keyless -partition KeylessSSL


'client assignPartition' successful.


Command Result : 0 (Success)


```

After the partition has been assigned, run `lunacm` from your virtual server and initialize the partition.

```

vm$ lunacm

lunacm (64-bit) v7.2.0-220. Copyright (c) 2018 SafeNet. All rights reserved.


  Available HSMs:


  Slot Id ->              0

  Label ->

  Serial Number ->        XXXXXXXXXXXXX

  Model ->                LunaSA 7.2.0

  Firmware Version ->     7.0.3

  Configuration ->        Luna User Partition With SO (PW) Signing With Cloning Mode

  Slot Description ->     Net Token Slot


  Current Slot Id: 0


lunacm:>partition init -label KeylessSSL -domain cloudflare


  Enter password for Partition SO: ********


  Re-enter password for Partition SO: ********


  You are about to initialize the partition.

  All contents of the partition will be destroyed.


  Are you sure you wish to continue?


  Type 'proceed' to continue, or 'quit' to quit now ->proceed


Command Result : No Error


```

---

## 2\. Generate a RSA key pair and certificate signing request (CSR)

Before running the commands below, check with your information security and/or cryptography team to confirm the approved key creation procedures for your organization.

```

# cmu generatekeypair -keyType=RSA -modulusBits=2048 -publicExponent=65537 -sign=1 -verify=1 -labelpublic=myrsakey -labelprivate=myrsakey -keygenmech=1


Please enter password for token in slot 0 : ********


# cmu list


Please enter password for token in slot 0 : ********

handle=51 label=myrsakey

handle=48 label=myrsakey


```

Using the key created in the previous step, generate a CSR that can be sent to a publicly trusted Certificate Authority (CA) for signing.

```

# cmu requestCertificate -c="US" -o="Example, Inc." -cn="azure-dedicatedhsm.example.com" -s="California" -l="San Francisco" -publichandle=48 -privatehandle=51 -outputfile="rsa.csr" -sha256withrsa


Please enter password for token in slot 0 : ********

Using "CKM_SHA256_RSA_PKCS" Mechanism


```

---

## 3\. Obtain and upload a signed certificate from your Certificate Authority (CA)

Provide the CSR created in the previous step to your organization's preferred CA, demonstrate control of your domain as requested, and then download the signed SSL certificates. Follow the instructions provided in [Upload Keyless SSL Certificates](https://developers.cloudflare.com/ssl/keyless-ssl/configuration/cloudflare-tunnel/#3-upload-keyless-ssl-certificates).

---

## 4\. Modify your gokeyless config file and restart the service

Lastly, we need to modify the configuration file that the key server will read on startup. Be sure to change the `object=mykey` and `pin-value=username:password` values to match the key label you provided and CU user you created.

Open `/etc/keyless/gokeyless.yaml` and immediately after:

YAML

```

private_key_stores:

  - dir: /etc/keyless/keys


```

add:

YAML

```

- uri: pkcs11:token=KeylessSSL;object=myrsakey?module-path=/usr/safenet/lunaclient/lib/libCryptoki2_64.so&pin-value=password&max-sessions=1


```

With the config file saved, restart `gokeyless` and verify it started successfully.

Terminal window

```

sudo systemctl restart gokeyless.service

sudo systemctl status gokeyless.service -l


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/","name":"Hardware security modules"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/azure-dedicated-hsm/","name":"Azure Dedicated HSM"}}]}
```

---

---
title: Azure Managed HSM
description: This tutorial uses Microsoft Azure's Managed HSM to deploy a VM with the Keyless SSL daemon. Follow these instructions to deploy your keyless server.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Azure Managed HSM

This tutorial uses [Microsoft Azure’s Managed HSM ↗](https://azure.microsoft.com/en-us/updates/akv-managed-hsm-public-preview/) — a FIPS 140-2 Level 3 certified implementation — to deploy a VM with the Keyless SSL daemon.

---

## Before you start

Make sure you have:

* Followed Microsoft's [tutorial ↗](https://docs.microsoft.com/en-us/azure/key-vault/managed-hsm/quick-create-cli) for provisioning and activating the managed HSM
* Set up a VM for your key server

---

## 1\. Create a VM

Create a VM where you will deploy the keyless daemon.

---

## 2\. Deploy the keyless server

Follow [these instructions](https://developers.cloudflare.com/ssl/keyless-ssl/configuration/cloudflare-tunnel/#4-set-up-and-activate-key-server) to deploy your keyless server.

---

## 3\. Set up the Azure CLI

Set up the Azure CLI (used to access the private key).

For example, if you were using macOS:

Terminal window

```

brew install azure-cli


```

---

## 4\. Set up the Managed HSM

1. Log in through the Azure CLI and create a resource group for the Managed HSM in one of the supported regions:  
Terminal window  
```  
az login  
az group create --name HSMgroup --location southcentralus  
```  
Note  
For a list of supported regions, see the [Microsoft documentation ↗](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=key-vault).
2. [Create, provision, and activate ↗](https://docs.microsoft.com/en-us/azure/key-vault/managed-hsm/quick-create-cli) the HSM.
3. Add your private key to the `keyvault`, which returns the URI you need for **Step 4**:  
```  
az keyvault key import --hsm-name "KeylessHSM" --name "hsm-pub-keyless" --pem-file server.key  
```
4. If the key server is running in an Azure VM in the same account, use **Managed services** for authorization:  
   1. Enable managed services on the VM in the UI.  
   2. Give your service user (associated with your VM) HSM sign permissions  
   ```  
   az keyvault role assignment create  --hsm-name KeylessHSM --assignee $(az vm identity show --name "hsmtestvm" --resource-group "HSMgroup" --query principalId -o tsv) --scope / --role "Managed HSM Crypto User"  
   ```
5. In the `gokeyless` YAML file, add the URI from **Step 2** under `private_key_stores`. See our [README ↗](https://github.com/cloudflare/gokeyless/blob/master/README.md) for an example.

## 5\. Restart gokeyless

Once you save the config file, restart `gokeyless` and verify that it started successfully:

Terminal window

```

sudo systemctl restart gokeyless.service

sudo systemctl status gokeyless.service -l


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/","name":"Hardware security modules"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/azure-managed-hsm/","name":"Azure Managed HSM"}}]}
```

---

---
title: Configuration
description: Configure the key server to work with hardware security modules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configuration

Important

Carefully review the manufacturer documentation for your HSM and properly restrict access to the key server.

To get started with your PKCS#11 token you will need to initialize it with a private key, PIN, and token label. The instructions to do this will be specific to each hardware device, and you should follow the instructions provided by your vendor. You will also need to find the path to your `module`, a shared object file (`.so`). Having initialized your device, you can query it to check your token label with:

Terminal window

```

pkcs11-tool --module <module path> --list-token-slots


```

You will also want to check the label of the private key you imported (or generated). Run the following command and look for a `Private Key Object`:

Terminal window

```

pkcs11-tool --module <module path> --pin <pin> \

    --list-token-slots --login --list-objects


```

You now have all the information you need to use your PKCS#11 token with the Keyless server, by adding to the `private_key_stores` section in the configuration file. You can specify the key pairs that you want Keyless to have access to in the [configuration file using the PKCS#11 URI ↗](https://tools.ietf.org/html/rfc7512) format.

## PKCS#11 URI

A PKCS#11 URI is a sequence of attribute value pairs separated by a semicolon that form a one-level path component, optionally followed by a query. The general form represented is:

```

pkcs11:path-component[?query-component]


```

The URI path component contains attributes that identify a resource. The query component can contain a few attributes that may be needed to retrieve the resource identified by the URI path component. Attributes in the path component are delimited by the `;` character, and attributes in the query component use `&` as a delimiter. All attributes are URL-encoded.

Keyless requires the following three attributes be specified:

* **Module**: use `module-path` to locate the PKCS#11 module library.
* **Token**: use `serial`, `slot-id`, or `token` to specify the PKCS#11 token.
* **Slot**: use `id` or `object` to specify the PKCS#11 key pair.

For certain modules, a query attribute `max-sessions` is required in order to prevent opening too many sessions to the module. Certain additional attributes, such as `pin-value`, may be necessary depending on the situation. Refer to the documentation for your PKCS#11 module for more details.

## Examples

Here are some examples of PKCS#11 URIs for keys stored on various modules:

```

private_key_stores:

- uri: pkcs11:token=SoftHSM2%20RSA%20Token;id=%03?module-path=/usr/lib64/libsofthsm2.so&pin-value=1234

- uri: pkcs11:token=accelerator;object=thaleskey?module-path=/opt/nfast/toolkits/pkcs11/libcknfast.so

- uri: pkcs11:token=YubiKey%20PIV;id=%00?module-path=/usr/lib64/libykcs11.so&pin-value=123456&max-sessions=1

- uri: pkcs11:token=elab2parN;id=%04?module-path=/usr/lib/libCryptoki2_64.so&pin-value=crypto1


```

## Limitations

For now, only one PKCS#11 module can be used at a time, so if you have keys on multiple HSMs, we recommend [using p11-glue to consolidate access through one module ↗](https://p11-glue.github.io/p11-glue/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/","name":"Hardware security modules"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/configuration/","name":"Configuration"}}]}
```

---

---
title: Entrust nShield Connect
description: Learn how to use Keyless SSL with Entrust nShield Connect.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Entrust nShield Connect

Note

This example assumes you have already configured the nShield Connect device and generated or imported your private keys.

Since the keys are already in place, we merely need to build the configuration file that the key server will read on startup. In this example the device contains a single RSA key pair.

We ask `pkcs11-tool` (provided by the `opensc` package) to display the objects stored in the token:

```

pkcs11-tool --module /opt/nfast/toolkits/pkcs11/libcknfast.so -O


```

```

Using slot 0 with a present token (0x1d622495)

Private Key Object; RSA

  label:      rsa-privkey

  ID:         105013281578de42ea45f5bfac46d302fb006687

  Usage:      decrypt, sign, unwrap

warning: PKCS11 function C_GetAttributeValue(ALWAYS_AUTHENTICATE) failed: rv = CKR_ATTRIBUTE_TYPE_INVALID (0x12)


Public Key Object; RSA 2048 bits

  label:      rsa-privkey

  ID:         105013281578de42ea45f5bfac46d302fb006687

  Usage:      encrypt, verify, wrap


```

The key piece of information is the label of the object, `rsa-privkey`. Open up `/etc/keyless/gokeyless.yaml` and immediately after

YAML

```

private_key_stores:

  - dir: /etc/keyless/keys


```

add

YAML

```

- uri: pkcs11:token=accelerator;object=rsa-privkey?module-path=/opt/nfast/toolkits/pkcs11/libcknfast.so&max-sessions=4


```

Save the config file, restart `gokeyless`, and verify it started successfully.

Terminal window

```

sudo systemctl restart gokeyless.service

sudo systemctl status gokeyless.service -l


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/","name":"Hardware security modules"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/entrust-nshield-connect/","name":"Entrust nShield Connect"}}]}
```

---

---
title: Fortanix Data Security Manager
description: Configure Keyless SSL with Fortanix Data Security Manager.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Fortanix Data Security Manager

You can use Cloudflare Keyless SSL with [Fortanix Data Security Manager (DSM) ↗](https://www.fortanix.com/platform/data-security-manager), a FIPS 140-2 Level 3 certified implementation.

You must have a [Data Security Manager Enterprise Tier ↗](https://www.fortanix.com/start-your-free-trial) and set up a group and an application assigned to the group.

For detailed guidance, follow the tutorial in the [Fortanix documentation ↗](https://support.fortanix.com/docs/fortanix-data-security-manager-with-cloudflare-integration#50-configure-fortanix-dsm). This guide is based on the Keyless SSL [public DNS](https://developers.cloudflare.com/ssl/keyless-ssl/configuration/public-dns/) option and has been tested using a virtual machine (VM) deployed to Azure running Ubuntu 22.04.3 LTS.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/","name":"Hardware security modules"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/fortanix-dsm/","name":"Fortanix Data Security Manager"}}]}
```

---

---
title: Google Cloud HSM
description: Learn how to use Keyless SSL with Google Cloud HSM.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Google Cloud HSM

This tutorial uses [Google Cloud HSM ↗](https://cloud.google.com/kms/docs/hsm) — a FIPS 140-2 Level 3 certified implementation.

---

## Before you start

Make sure that you have:

* Set up your [Google Cloud project ↗](https://cloud.google.com/kms/docs/quickstart#before-you-begin)

---

## 1\. Create a key ring

To set up the Google Cloud HSM, [create a key ring ↗](https://cloud.google.com/kms/docs/hsm#kms-create-key-hsm-web) and indicate its location.

Note:

Only [certain locations ↗](https://cloud.google.com/kms/docs/locations#hsm-regions) support Google Cloud HSM.

---

## 2\. Create a key

Create a key, including the following information:

| Field            | Value                                  |
| ---------------- | -------------------------------------- |
| Key ring         | The key ring you created in **Step 2** |
| Protection level | HSM                                    |
| Purpose          | Asymmetric Encrypt                     |

---

## 3\. Import the private key

After creating a key ring and key, [import the private key ↗](https://cloud.google.com/kms/docs/importing-a-key).

Note:

You need to [convert your key ↗](https://cloud.google.com/kms/docs/formatting-keys-for-import#formatting%5Fasymmetric%5Fkeys) from a PEM to DER format.

---

## 4\. Modify your gokeyless config file and restart the service

Once you’ve imported the key, copy the **Resource name** from the UI. Then, add this value to the `gokeyless` YAML file under `private_key_stores`.

With the config file saved, restart `gokeyless` and verify it started successfully.

Terminal window

```

sudo systemctl restart gokeyless.service

sudo systemctl status gokeyless.service -l


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/","name":"Hardware security modules"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/google-cloud-hsm/","name":"Google Cloud HSM"}}]}
```

---

---
title: IBM Cloud HSM
description: Learn how to use Keyless SSL with IBM Cloud HSM.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# IBM Cloud HSM

The example below was tested using [IBM Cloud HSM 7.0 ↗](https://console.bluemix.net/docs/infrastructure/hardware-security-modules/about.html#about-ibm-cloud-hsm), a FIPS 140-2 Level 3 certified implementation based on the Gemalto SafeNet Luna a750.

---

## Before you start

Make sure that you have:

* Initialized [your device ↗](https://console.bluemix.net/docs/infrastructure/hardware-security-modules/initialize%5Fhsm.html#initializing-the-ibm-cloud-hsm)
* Installed the [SafeNet client software ↗](https://cpl.thalesgroup.com/node/11350)

---

## 1\. Create, assign, and initialize a new partition

The first step is creating an HSM partition, which can be thought of as an independent logical HSM within your IBM Cloud HSM device.

```

vm$ ssh admin@hsm


[cloudflare-hsm.softlayer.com] lunash:>partition create -partition KeylessSSL


          Type 'proceed' to create the partition, or

          'quit' to quit now.

          > proceed

'partition create' successful.


Command Result : 0 (Success)


```

Next, the partition needs to be assigned to the client, in this case your key server.

Terminal window

```

[cloudflare-hsm.softlayer.com] lunash:>client assignpartition -client cloudflare-vm.softlayer.com -partition KeylessSSL


'client assignPartition' successful.


Command Result : 0 (Success)


```

After the partition has been assigned, run `lunacm` from your virtual server and initialize the partition.

```

vm$ lunacm

LunaCM v7.1.0-379. Copyright (c) 2006-2017 SafeNet.


    Available HSMs:


    Slot Id ->              0

    Label ->

    Serial Number ->        XXXXXXXXXXXXX

    Model ->                LunaSA 7.0.0

    Firmware Version ->     7.0.1

    Configuration ->        Luna User Partition With SO (PW) Signing With Cloning Mode

    Slot Description ->     Net Token Slot


    Current Slot Id: 0


lunacm:>partition init -label KeylessSSL -domain cloudflare


  Enter password for Partition SO: ********


  Re-enter password for Partition SO: ********


  You are about to initialize the partition.

  All contents of the partition will be destroyed.


  Are you sure you wish to continue?


  Type 'proceed' to continue, or 'quit' to quit now ->proceed


Command Result : No Error


```

---

## 2\. Generate RSA and ECDSA key pairs and certificate signing requests (CSRs)

Before running the commands below, check with your information security and/or cryptography team to confirm the approved key creation procedures for your organization.

When you perform this operation, you need define the ID field for the newly generated keys. It must be set to a big-endian hexadecimal integer value.

```

vm$ cmu generatekeypair -keyType=RSA -modulusBits=2048 -publicExponent=65537 -sign=1 -verify=1 -labelpublic=myrsakey -labelprivate=myrsakey -keygenmech=1  -id=a000

Please enter password for token in slot 0 : ********


# cmu generatekeypair -keyType=ECDSA -curvetype=3 -sign=1 -verify=1 -labelpublic=myecdsakey -labelprivate=myecdsakey -id=a001

Please enter password for token in slot 0 : ********


# cmu list

Please enter password for token in slot 0 : ********

handle=61   label=myecdsakey

handle=60   label=myecdsakey

handle=48   label=myrsakey

handle=45   label=myrsakey


```

Using the keys created in the previous step, generate CSRs that can be sent to a publicly trusted Certificate Authority (CA) for signing.

```

# cmu requestCertificate -c="US" -o="Example, Inc." -cn="ibm-cloudhsm.example.com" -s="California" -l="San Francisco" -publichandle=45 -privatehandle=48 -outputfile="rsa.csr" -sha256withrsa

Please enter password for token in slot 0 : ********

Using "CKM_SHA256_RSA_PKCS" Mechanism


# cmu requestCertificate -c="US" -o="Example, Inc." -cn="ibm-cloudhsm.example.com" -s="California" -l="San Francisco" -publichandle=60 -privatehandle=61 -outputfile="ecdsa.csr" -sha256withecdsa

Please enter password for token in slot 0 : ********

Using "CKM_ECDSA_SHA256" Mechanism


```

---

## 3\. Obtain and upload signed certificates from your Certificate Authority (CA)

Provide the CSRs created in the previous step to your organization's preferred CA, demonstrate control of your domain as requested, and then download the signed SSL certificates. Follow the instructions provided in [Upload Keyless SSL Certificates](https://developers.cloudflare.com/ssl/keyless-ssl/configuration/cloudflare-tunnel/#3-upload-keyless-ssl-certificates).

---

## 4\. Modify your gokeyless config file and restart the service

Lastly, we need to modify the configuration file that the key server will read on startup. Change the `object=mykey` and `pin-value=username:password` values to match the key label you provided and CU user you created.

Open `/etc/keyless/gokeyless.yaml` and immediately after:

YAML

```

private_key_stores:

  - dir: /etc/keyless/keys


```

add:

YAML

```

- uri: pkcs11:token=KeylessSSL;object=myrsakeyid=a000??module-path=/usr/safenet/lunaclient/lib/libCryptoki2_64.so&pin-value=password&max-sessions=1

- uri: pkcs11:token=KeylessSSL;object=myecdsakeyid=a001??module-path=/usr/safenet/lunaclient/lib/libCryptoki2_64.so&pin-value=password&max-sessions=1


```

With the config file saved, restart `gokeyless` and verify it started successfully.

Terminal window

```

sudo systemctl restart gokeyless.service

sudo systemctl status gokeyless.service -l


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/","name":"Hardware security modules"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/ibm-cloud-hsm/","name":"IBM Cloud HSM"}}]}
```

---

---
title: SoftHSMv2
description: Learn how to use Keyless SSL with SoftHSMv2.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# SoftHSMv2

Important

SoftHSMv2 should not be considered any more secure than storing private keys directly on disk. No attempt is made below to secure this installation; it is provided simply for demonstration purposes.

---

## 1\. Install and configure SoftHSMv2

First, we install SoftHSMv2 and configure it to store tokens in the default location `/var/lib/softhsm/tokens`. We also need to give the `softhsm` group permission to this directory as this is how the `keyless` user will access this directory.

Terminal window

```

sudo apt-get install -y softhsm2 opensc


#...


cat <<EOF | sudo tee /etc/softhsm/softhsm2.conf

directories.tokendir = /var/lib/softhsm/tokens

objectstore.backend = file

log.level = DEBUG

slots.removable = false

EOF


sudo mkdir /var/lib/softhsm/tokens

sudo chown root:softhsm $_

sudo chmod 0770 /var/lib/softhsm/tokens

sudo usermod -G softhsm keyless

sudo usermod -G softhsm $(whoami)


echo 'export SOFTHSM2_CONF=/etc/softhsm/softhsm2.conf' | tee -a ~/.profile

source ~/.profile


```

---

## 2\. Create a token and private keys, and generate CSRs

Next, we create a token in slot 0 called `test-token` and secure it with a PIN of `1234`. In this slot we’ll store the RSA keys for our SSL certificates for `keyless-softhsm.example.com`.

Terminal window

```

sudo -u keyless softhsm2-util --init-token --slot 0 --label test-token --pin 1234 --so-pin 4321


```

```

The token has been initialized.


```

Using cfssl, we generate the [private keys and Certificate Signing Requests (CSRs) ↗](https://github.com/cloudflare/cfssl), the latter of which will be sent to a Certificate Authority (CA) for signing.

Terminal window

```

cat <<EOF | tee csr.json

{

    "hosts": [

        "keyless-softhsm.example.com"

    ],

    "CN": "keyless-softhsm.example.com",

    "key": {

        "algo": "rsa",

        "size": 2048

    },

    "names": [{

        "C": "US",

        "L": "San Francisco",

        "O": "TLS Fun",

        "OU": "Technical Operations",

        "ST": "California"

    }]

}

EOF


cfssl genkey csr.json | cfssljson -bare certificate


```

```

2018/08/12 00:52:22 [INFO] generate received request

2018/08/12 00:52:22 [INFO] received CSR

2018/08/12 00:52:22 [INFO] generating key: rsa-2048

2018/08/12 00:52:22 [INFO] encoded CSR


```

---

## 3\. Convert and import the key

Now that the key has been generated, it’s time to load it into the slot we created. Before doing so, we need to convert from PKCS#1 to PKCS#8 format. During import, we specify the token and PIN from token initialization and provide a unique hexadecimal ID and label to the key.

Terminal window

```

openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in certificate-key.pem -out certificate-key.p8

sudo chown keyless certificate-key.p8


sudo -u keyless softhsm2-util --pin 1234 --import ./certificate-key.p8 --token test-token --id a000 --label rsa-privkey


```

```

Found slot 915669571 with matching token label.

The key pair has been imported.


```

After importing we ask `pkcs11-tool` to confirm the objects have been successfully stored in the token.

Terminal window

```

sudo -u keyless pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so -l -p 1234 --token test-token --list-objects


```

```

Public Key Object; RSA 2048 bits

  label:      rsa-privkey

  ID:         a000

  Usage:      verify

Private Key Object; RSA

  label:      rsa-privkey

  ID:         a000

  Usage:      sign


```

---

## 4\. Modify your gokeyless config file and restart the service

With the keys in place, it’s time to build the configuration file that the key server will read on startup. The `id` refers to the hexadecimal ID you provided to the `softhsm2-util` import statement; we used `a000` so it is encoded as `%a0%00`. The `module-path` will vary slightly based on the Linux distribution you are using. On Debian it should be `/usr/lib/softhsm/libsofthsm2.so`.

Open up `/etc/keyless/gokeyless.yaml` and immediately after

YAML

```

private_key_stores:

  - dir: /etc/keyless/keys


```

add

YAML

```

- uri: pkcs11:token=test-token;id=%a0%00?module-path=/usr/lib/softhsm/libsofthsm2.so&pin-value=1234&max-sessions=1


```

Save the config file, restart `gokeyless`, and verify it started successfully.

Terminal window

```

sudo systemctl restart gokeyless.service

sudo systemctl status gokeyless.service -l


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/","name":"Hardware security modules"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/hardware-security-modules/softhsmv2/","name":"SoftHSMv2"}}]}
```

---

---
title: High availability
description: Deploy Keyless SSL key servers with high availability.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# High availability

The Cloudflare Keyless SSL server runs as a single binary with minimal dependencies and is designed to be robust and reliable. However, the network between your key server and Cloudflare may not be, which could prevent new TLS connections.

For this reason, we strongly recommend that you run at least two key servers in a high availability configuration behind a load balancer. Set up health checks for each key server on the configured TCP port—2407 by default and failover as necessary or round-robin between active (healthy) key servers.

From a network availability and performance perspective, advertise the IP address of your key server from multiple data centers (an anycast setup) so the Cloudflare global network can route to the closest key server via BGP. When you use anycast routing, you can also safely take a data center offline to perform maintenance.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/reference/high-availability/","name":"High availability"}}]}
```

---

---
title: Keyless delegation
description: Delegate certificate signing to downstream key servers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Keyless delegation

Keyless Delegation is Cloudflare's implementation of the emerging delegated credentials standard ([RFC 9345 ↗](https://www.rfc-editor.org/rfc/rfc9345.html)). When you upload a certificate for use with Keyless that has the special extension permitting the use of delegated credentials, Cloudflare will automatically produce a delegated credential and use it at the edge with clients that support this feature. The handshakes will complete without the extra latency induced by reaching back to the Keyless Server, and there are [additional advantages to flexibility in algorithm choice ↗](https://blog.cloudflare.com/keyless-delegation/).

Behind the scenes we periodically create delegated credentials and sign them via Keyless, through the same mechanism used to sign the Certificate Verify messages our servers send when using Keyless. These credentials have a short lifetime, ensuring that if you disable Keyless the credentials created will become invalid within 24 hours. Supporting clients validate the credential, and the server can use the key it generated to sign the response to the TLS handshake without the round trip.

For security reasons certificates must contain a special identifier for use with delegated credentials. This takes the form of an optional X509 extension with NULL contents and the OID 1.3.6.1.4.1.44363.44\. Your CA may need to make code changes to support delegated credentials.

Currently very few clients support delegated credentials, and only a handful of certificate authorities will issue certificates with the extension. We have had success with DigiCert. Firefox 77 and later support delegated credentials.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/reference/keyless-delegation/","name":"Keyless delegation"}}]}
```

---

---
title: Key server metrics
description: Prometheus metrics exposed by the gokeyless key server.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Key server metrics

The gokeyless key server exposes a [Prometheus ↗](https://prometheus.io/) metrics endpoint that you can use to monitor signing performance, error rates, connection health, and certificate expiry. This endpoint can also be scraped by the OpenTelemetry Collector Prometheus receiver, making the metrics available to any OpenTelemetry-compatible backend.

## Metrics endpoint

By default, metrics are served at:

```

http://<host>:2406/metrics


```

The port is configurable via the `metrics_port` key in your configuration file, the `--metrics-port` flag, or the `KEYLESS_METRICS_PORT` environment variable.

The endpoint serves only `/metrics`. There are no additional HTTP endpoints such as `/health` or `/debug`.

---

## Histogram buckets

All histogram metrics share the same bucket configuration: 15 exponential buckets starting at 100 microseconds, doubling each step up to approximately 1.64 seconds, plus a final `+Inf` bucket.

| Bucket | Upper bound             |
| ------ | ----------------------- |
| 1      | 100 µs                  |
| 2      | 200 µs                  |
| 3      | 400 µs                  |
| 4      | 800 µs                  |
| 5      | 1.6 ms                  |
| 6      | 3.2 ms                  |
| 7      | 6.4 ms                  |
| 8      | 12.8 ms                 |
| 9      | 25.6 ms                 |
| 10     | 51.2 ms                 |
| 11     | 102 ms                  |
| 12     | 205 ms                  |
| 13     | 410 ms                  |
| 14     | 819 ms                  |
| 15     | \~1.64 s                |
| +Inf   | Anything above \~1.64 s |

Note

When using a hardware security module (HSM) with a PKCS#11 session pool, the pool wait timeout is hardcoded at 10 seconds. A pool exhaustion event will therefore always appear in the `+Inf` bucket. Spikes in `+Inf` observations on signing operations with `error="cryptography error"` are a direct indicator of PKCS#11 session pool saturation.

---

## Metrics reference

### `keyless_requests`

**Type:** Counter  
**Labels:** `opcode`

Counts every incoming request received over an established connection, regardless of outcome. Incremented once per request before any processing begins.

The `opcode` label uses the full constant name from the gokeyless protocol.

#### RSA operations

| opcode label       | Wire value | Description                                                                   |
| ------------------ | ---------- | ----------------------------------------------------------------------------- |
| OpRSADecrypt       | 0x01       | RSA raw decryption — used in TLS RSA key exchange (deprecated in TLS 1.3)     |
| OpRSASignMD5SHA1   | 0x02       | RSA PKCS#1 v1.5 signature over MD5+SHA1 combined hash — TLS 1.0/1.1 handshake |
| OpRSASignSHA1      | 0x03       | RSA PKCS#1 v1.5 signature over SHA1                                           |
| OpRSASignSHA224    | 0x04       | RSA PKCS#1 v1.5 signature over SHA224                                         |
| OpRSASignSHA256    | 0x05       | RSA PKCS#1 v1.5 signature over SHA256                                         |
| OpRSASignSHA384    | 0x06       | RSA PKCS#1 v1.5 signature over SHA384                                         |
| OpRSASignSHA512    | 0x07       | RSA PKCS#1 v1.5 signature over SHA512                                         |
| OpRSAPSSSignSHA256 | 0x35       | RSASSA-PSS signature over SHA256 — primary RSA operation in TLS 1.3           |
| OpRSAPSSSignSHA384 | 0x36       | RSASSA-PSS signature over SHA384                                              |
| OpRSAPSSSignSHA512 | 0x37       | RSASSA-PSS signature over SHA512                                              |

#### ECDSA operations

| opcode label       | Wire value | Description                                                      |
| ------------------ | ---------- | ---------------------------------------------------------------- |
| OpECDSASignMD5SHA1 | 0x12       | ECDSA signature over MD5+SHA1 combined hash                      |
| OpECDSASignSHA1    | 0x13       | ECDSA signature over SHA1                                        |
| OpECDSASignSHA224  | 0x14       | ECDSA signature over SHA224                                      |
| OpECDSASignSHA256  | 0x15       | ECDSA signature over SHA256 — most common in TLS 1.2 and TLS 1.3 |
| OpECDSASignSHA384  | 0x16       | ECDSA signature over SHA384                                      |
| OpECDSASignSHA512  | 0x17       | ECDSA signature over SHA512                                      |

#### Other signing

| opcode label  | Wire value | Description                                                                  |
| ------------- | ---------- | ---------------------------------------------------------------------------- |
| OpEd25519Sign | 0x18       | Ed25519 signature over an arbitrary-length payload (not a pre-hashed digest) |

#### Sealing and infrastructure operations

| opcode label | Wire value | Description                                                                                           |
| ------------ | ---------- | ----------------------------------------------------------------------------------------------------- |
| OpSeal       | 0x21       | Encrypt a blob using the server's sealing key — used for TLS session tickets                          |
| OpUnseal     | 0x22       | Decrypt a blob previously encrypted by OpSeal. Returns ErrExpired if the sealing key has rotated      |
| OpRPC        | 0x23       | Execute a named function registered on the server. Available to all connection types                  |
| OpCustom     | 0x24       | Execute a custom function set in the server configuration. Available to unrestricted connections only |
| OpPing       | 0xF1       | Health check — the server echoes the payload back as OpPong with no HSM or key lookup involved        |

---

### `keyless_request_exec_duration_per_opcode`

**Type:** Histogram  
**Labels:** `type`, `error`

Measures the time to execute a single operation, from when processing begins to when a response is produced. For operations backed by a PKCS#11 HSM, this includes the full time waiting for a session from the pool plus the HSM cryptographic operation time.

This metric does not include time a request spends waiting for a connection semaphore slot. That is captured by [keyless\_request\_total\_duration\_per\_opcode](#keyless%5Frequest%5Ftotal%5Fduration%5Fper%5Fopcode).

#### `type` label

Opcodes are grouped into coarser categories for this label:

| type label | Opcodes included                                      |
| ---------- | ----------------------------------------------------- |
| rsa        | OpRSADecrypt, all OpRSASign\*, all OpRSAPSSSign\*     |
| ecdsa      | All OpECDSASign\*                                     |
| ed25519    | OpEd25519Sign                                         |
| rpc        | OpRPC                                                 |
| custom     | OpCustom                                              |
| other      | OpSeal, OpUnseal, OpPing, OpPong, OpResponse, OpError |
| unknown    | Any unrecognised opcode byte                          |

Note

`OpPing` is grouped into `other` alongside `OpSeal` and `OpUnseal`. Ping round-trip latency cannot be separated from seal and unseal operation latency in this metric.

#### `error` label

For successful requests the value is `no error`. All other values indicate a failed operation.

| error label                                       | Description                             | Common cause                                                                                        |
| ------------------------------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------- |
| no error                                          | Operation completed successfully        | —                                                                                                   |
| cryptography error                                | HSM or signing operation failed         | PKCS#11 session pool exhaustion (resource pool timed out), HSM returned an error, key type mismatch |
| key not found due to no matching SKI/SNI/ServerIP | Key lookup returned no result           | Key not loaded in keystore, incorrect SKI in request                                                |
| read failure                                      | I/O read error during the operation     | Disk error reading key file                                                                         |
| version mismatch                                  | Protocol version not supported          | Client and server version skew                                                                      |
| bad opcode                                        | Unknown opcode received                 | OpCustom sent with no custom handler configured                                                     |
| unexpected opcode                                 | A response opcode was used as a request | Client sent OpPong, OpResponse, or OpError as a request                                             |
| malformed message                                 | TLV parse failure                       | Corrupt or truncated packet                                                                         |
| internal error                                    | Non-cryptographic server-side failure   | Sealer is nil, RPC dispatch error                                                                   |
| certificate not found                             | Certificate lookup failed               | Certificate not loaded                                                                              |
| sealing key expired                               | OpUnseal blob is too old to decrypt     | TLS session ticket key rotation — blob sealed with a key that has since been retired                |
| remote configuration error                        | Remote key server is misconfigured      | Key points to an unreachable or misconfigured remote key server                                     |

---

### `keyless_request_total_duration_per_opcode`

**Type:** Histogram  
**Labels:** `type`, `error` (same values as [keyless\_request\_exec\_duration\_per\_opcode](#keyless%5Frequest%5Fexec%5Fduration%5Fper%5Fopcode))

Measures the total time to satisfy a request, from when the request packet is read off the wire to when the response bytes are written back to the client.

```

total_duration = exec_duration + response_write_time


```

Both timestamps are captured after the connection semaphore is already held, so semaphore queue wait time is not included in either histogram. Under normal load, total duration and exec duration are approximately equal. A growing gap between them indicates slow writes back to the client — for example, network backpressure between the key server and the Cloudflare edge.

---

### `keyless_key_load_duration`

**Type:** Histogram  
**Labels:** None

Measures the time taken by the keystore to locate and return the private key for each request, keyed by SKI, SNI, and server IP.

* For file-backed keystores, this is a map lookup and is typically sub-millisecond.
* For PKCS#11 or HSM keystores, this may include a network round-trip to the HSM if key references are not cached in memory.

This metric is recorded for all signing and decryption operations: `OpRSADecrypt`, all `OpRSASign*`, all `OpRSAPSSSign*`, all `OpECDSASign*`, and `OpEd25519Sign`.

It is **not** recorded for `OpPing`, `OpSeal`, `OpUnseal`, `OpRPC`, or `OpCustom`, which do not require a private key lookup.

---

### `keyless_failed_connection`

**Type:** Counter  
**Labels:** None

Counts connection-level transport failures. This metric reflects problems at the network or TLS layer — it does not count signing errors or key lookup failures, which are reported in the `error` label of the duration histograms.

| Scenario                                             | Counted? |
| ---------------------------------------------------- | -------- |
| TLS handshake failure                                | No       |
| Client disconnected before TLS handshake (EOF)       | No       |
| Failure determining connection trust level after TLS | Yes      |
| Non-EOF read error on an established connection      | Yes      |
| Write error when delivering a response               | Yes      |
| Read timeout — graceful connection drain             | No       |
| Signing error, including PKCS#11 pool timeout        | No       |
| Key not found                                        | No       |

---

### `certificate_expiration_timestamp_seconds`

**Type:** Gauge  
**Labels:** `source`, `serial_no`, `cn`, `hostnames`, `ca`, `server`, `client`

Reports the expiration time (`NotAfter`) of each certificate loaded by the key server as a Unix timestamp. One time series is emitted per certificate.

This metric is updated:

* At startup, for the server authentication certificate (`auth_cert`) and the Cloudflare CA certificate (`cloudflare_ca_cert`).
* On each successful inbound TLS connection, for the peer certificates presented by the connecting client.

| Label      | Description                                                                            |
| ---------- | -------------------------------------------------------------------------------------- |
| source     | File path for startup certs; listener: <addr> for peer certs from incoming connections |
| serial\_no | Certificate serial number                                                              |
| cn         | Subject Common Name                                                                    |
| hostnames  | Sorted, comma-separated list of DNS Subject Alternative Names                          |
| ca         | 1 if the certificate is a CA certificate, 0 otherwise                                  |
| server     | 1 if the certificate includes ExtKeyUsageServerAuth, 0 otherwise                       |
| client     | 1 if the certificate includes ExtKeyUsageClientAuth, 0 otherwise                       |

Note

`server_utilization` is a registered `GaugeVec` metric that is never written to by the key server. Because no label values are ever set, it emits no time series in the `/metrics` output at all. Do not use it.

---

## Example PromQL queries

### Signing throughput by key type

```

sum by (opcode) (rate(keyless_requests[1m]))


```

### Error rate by error type

```

sum by (error) (

  rate(keyless_request_exec_duration_per_opcode_count{error!="no error"}[5m])

)


```

### 99th percentile signing latency for RSA

```

histogram_quantile(

  0.99,

  rate(keyless_request_exec_duration_per_opcode_bucket{type="rsa"}[5m])

)


```

A value approaching 10 seconds indicates PKCS#11 session pool exhaustion. Refer to [Scaling and benchmarking](https://developers.cloudflare.com/ssl/keyless-ssl/reference/scaling-and-benchmarking/) and your HSM documentation for guidance on increasing the session pool size.

### 99th percentile key load latency

```

histogram_quantile(0.99, rate(keyless_key_load_duration_bucket[5m]))


```

A spike here without a corresponding spike in exec duration suggests the keystore lookup itself is slow — a possible disk I/O issue or PKCS#11 object enumeration delay.

### Connection failure rate

```

rate(keyless_failed_connection_total[5m])


```

A sustained non-zero rate indicates network or TLS problems between the Cloudflare network and your key server.

### Alert on certificate expiry within 30 days

```

(certificate_expiration_timestamp_seconds - time()) / 86400 < 30


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/reference/metrics/","name":"Key server metrics"}}]}
```

---

---
title: Scaling and benchmarking
description: Scale and benchmark Keyless SSL key servers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Scaling and benchmarking

Cloudflare's Keyless SSL technology was designed to scale to accommodate any sized workload using vertical and horizontal scaling, and pre-computation techniques wherever possible, such as ECDSA. The goals of the architectural design of the key server are to minimize latency while maximizing signing operations per second.

Each key server uses a worker pool model, with incoming client connections handled by its own pair of reader/writer goroutines and cryptographic work done in separate worker goroutines pulled from a global pool.

Where needed, multiple key servers can be deployed and balanced between using your preferred ingress load balancing configuration. For full high availability, make sure to deploy sufficient key servers to handle twice the expected workload.

---

## Key type

Key servers support both ECDSA and RSA keys, though signatures for RSA are an [order of magnitude more expensive ↗](https://blog.cloudflare.com/ecdsa-the-digital-signature-algorithm-of-a-better-internet/) to compute and thus consider type of keys used when planning the number of key servers in your deployment.

ECDSA signing can be broken down into two steps. Since the first step — generating random values (to be used later with the private key and message to be signed) — represents the majority of the computational cost, we pre-generate these random values to significantly reduce latency. ECDSA signing requests are computationally isolated from RSA signing requests using separate worker pools to keep them as fast as possible.

Additional details can be found in the [gokeyless server readme file ↗](https://github.com/cloudflare/gokeyless#readme) file.

---

## Benchmarks

We conducted benchmarks using [Cloudflare's gokeyless bench tool ↗](https://github.com/cloudflare/gokeyless/tree/master/cmd/bench) on a then current-generation, compute-optimized EC2 instance ([c5.xlarge ↗](https://aws.amazon.com/ec2/instance-types/c5/)). This particular instance has 4 vCPUs powered by 3.0 GHz Intel Xeon processors:

```

c5$ cat /proc/cpuinfo|grep "model name"

model name  : Intel(R) Xeon(R) Platinum 8124M CPU @ 3.00GHz

model name  : Intel(R) Xeon(R) Platinum 8124M CPU @ 3.00GHz

model name  : Intel(R) Xeon(R) Platinum 8124M CPU @ 3.00GHz

model name  : Intel(R) Xeon(R) Platinum 8124M CPU @ 3.00GHz


```

By default, bench runs with one worker goroutine per core (4) and a maximum number of operating system threads equal to the total number of cores (in this case, `GOMAXPROCS=4`). As expected and explained above, ECDSA signature performance far exceeds that of RSA. The [results show](#results) that each core of this c5.xl machine can perform over 10,000 ECDSA signing operations/second and approximately 200 RSA signing operations/second.

When planning your deployment, determine the maximum number of new TLS connections per second you expect to terminate using a given key server and scale accordingly. For full high availability, each data center running keyless should be able to terminate the full workload that you anticipate.

### Results

#### ECDSA

```

c5$ bench -ski $ECDSA_SKI -op ECDSA-SHA256 -bandwidth -duration 60s

Total operations completed: 2661570

Average operation duration: 22.543µs


```

#### RSA

```

c5$ bench -ski $RSA_SKI -op RSA-SHA256 -bandwidth -duration 60s

Total operations completed: 46560

Average operation duration: 1.288659ms.


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/keyless-ssl/reference/scaling-and-benchmarking/","name":"Scaling and benchmarking"}}]}
```

---

---
title: Troubleshooting
description: Review how to troubleshoot issues when using Cloudflare Keyless SSL.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

## Check the logs

To check logs, use a command similar to the following.

* systemd: `sudo journalctl -f -u gokeyless`
* upstart/sysvinit: `sudo tail -f /var/log/gokeyless.log`

## Enable debug logging

To enable debug logging, use a command similar to the following.

Terminal window

```

cd /etc/keyless

sudo -u keyless gokeyless --loglevel 0


```

## Browsers are seeing a TLS connection failure after trying to connect

1. Make sure your key server is accessible from outside your network (tcp/2407).
2. Provide a packet capture:`sudo tcpdump -nni <interface> -s 0 -w keyless-$(date +%s).pcap port 2407`

## Clients are connecting, but immediately aborting

If you run `gokeyless` with debug logging enabled, and you see logs like this:

```

[DEBUG] connection 162.158.57.220:37490: reading half closed by client

[DEBUG] connection 162.158.57.220:37490: server closing connection

[DEBUG] connection 162.158.57.220:37490 removed

[DEBUG] spawning new connection: 162.158.57.220:37862

[DEBUG] connection 162.158.57.220:37862: reading half closed by client

[DEBUG] connection 162.158.57.220:37862: server closing connection

[DEBUG] connection 162.158.57.220:37862 removed


```

These logs likely indicate that the key server is not using an appropriate server or .`PEM` file and the client is aborting the connection after the certificate exchange. The certificate must be signed by the keyless CA and the SANs must include the hostname of the keyless server. Here is a valid example for a keyless server located at `11aa40b4a5db06d4889e48e2f.example.com` (note the Subject Alternative Name and Authority Key Identifier):

Terminal window

```

openssl x509 -in server.pem -noout -text -certopt no_subject,no_header,no_version,no_serial,no_signame,no_validity,no_subject,no_issuer,no_pubkey,no_sigdump,no_aux | sed -e 's/^        //'


```

```

X509v3 extensions:

    X509v3 Key Usage: critical

        Digital Signature, Key Encipherment

    X509v3 Extended Key Usage:

        TLS Web Server Authentication

    X509v3 Basic Constraints: critical

        CA:FALSE

    X509v3 Subject Key Identifier:

        DD:24:97:F1:A9:F1:4C:73:D9:1B:44:EC:A1:C3:10:E9:F0:41:98:BB

    X509v3 Authority Key Identifier:

        keyid:29:CE:8F:F1:9D:4C:BA:DE:55:78:D7:A6:29:E9:C5:FD:1D:9D:21:48


    X509v3 Subject Alternative Name:

        DNS:11aa40b4a5db06d4889e48e2f.example.com

    X509v3 CRL Distribution Points:


        Full Name:

          URI:http://ca.cfdata.org/api/v1/crl/key_server


```

## The gokeyless binary cannot load the CA file

Ensure permissions are correct on all keys and certificates installed on the server.

## Keyless is affecting to unanticipated hosts

You will need to either provide a certificate for only those hosts or change the priority of the certificate in the **SSL/TLS** app of your Cloudflare dashboard.

## Key servers on Windows

Cloudflare currently only provide packages for the supported GNU/Linux distributions as per the [Cloudflare package repository ↗](https://pkg.cloudflare.com/).

However, the key server is open source so you may attempt to build and deploy a binary, but running on Windows is not a supported configuration so you may experience problems that Cloudflare will not be able to help with.

## Key server multi-domain support

You can use the same key server for multiple domains.

However, if you do, you will need to add the hostname and the Zone ID of the new domain to the `gokeyless.yaml` file.

## Additional questions

Contact your account team or [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: Upgrade your key server
description: Upgrade your Keyless SSL key server to the latest version.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Upgrade your key server

Periodically, you may need to update your key server when using Cloudflare's Keyless SSL.

To upgrade your key server:

1. Back up the contents of `/etc/keyless`.
2. Update your OS’ package listings, for example, `apt-get update` or `yum update`.
3. Upgrade the gokeyless server:
4. Debian/Ubuntu: `apt-get upgrade gokeyless`
5. RHEL/CentOS: `yum install gokeyless`
6. Restart the keyless instance:
7. systemd: `service gokeyless restart`
8. upstart/sysvinit: `/etc/init.d/gokeyless restart`
9. Confirm that HTTPS connections are working as expected.

Warning

If you are running a [high availability configuration](https://developers.cloudflare.com/ssl/keyless-ssl/reference/high-availability/), upgrade one server at a time as new TLS connections will fail to terminate at Cloudflare's global network without a functioning key server.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/keyless-ssl/","name":"Keyless SSL"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/keyless-ssl/upgrading-your-key-server/","name":"Upgrade your key server"}}]}
```

---

---
title: Post-quantum cryptography (PQC)
description: Get an overview of how Cloudflare is deploying post-quantum cryptography to protect you against harvest now, decrypt later.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Post-quantum cryptography (PQC)

Post-quantum cryptography (PQC) refers to cryptographic algorithms that have been designed to resist attacks from [quantum computers ↗](https://www.cloudflare.com/learning/ssl/quantum/what-is-quantum-computing/). Cloudflare has been researching and [writing about post-quantum ↗](https://blog.cloudflare.com/tag/post-quantum/) since 2017, and is targeting 2029 to be fully post-quantum secure across its entire product suite — refer to [Cloudflare targets 2029 for full post-quantum security ↗](https://blog.cloudflare.com/post-quantum-roadmap/) for the full roadmap.

To protect you against the risk of [harvest-now, decrypt-later attacks ↗](https://en.wikipedia.org/wiki/Harvest%5Fnow,%5Fdecrypt%5Flater), and considering all the [connections](#three-connections-in-the-life-of-a-request) that take place when your website or application is on Cloudflare, we have deployed and are actively expanding the use of [post-quantum hybrid key agreement](#hybrid-key-agreement). In parallel, Cloudflare is beginning to deploy [post-quantum signatures](#post-quantum-signatures) to protect authentication against future quantum attacks.

Refer to [Cloudflare Radar ↗](https://radar.cloudflare.com/adoption-and-usage#post-quantum-encryption-adoption) for current statistics on the adoption of PQ encryption in requests to Cloudflare, and visit [Cloudflare Radar's browser support check ↗](https://radar.cloudflare.com/post-quantum#browser-support) to check if your browser is secured using PQ key agreement.

TLS 1.3

Cloudflare post-quantum key agreements are only supported in protocols based on TLS 1.3 (including HTTP/3) and are disabled for websites in [FIPS mode](https://developers.cloudflare.com/cloudflare-one/traffic-policies/http-policies/tls-decryption/#fips-compliance).

## Three building blocks of TLS

Before TLS can protect your communications, three cryptographic algorithms have to be agreed on during the [TLS handshake ↗](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/):

* **Symmetric ciphers:** Algorithms used to encrypt and decrypt data, ensuring confidentiality and integrity (such as `CHACHA20-POLY1305`).
* **Key agreement:** A cryptographic protocol that allows client and server to safely agree on a shared key (such as `ECDH`).
* **Signature algorithms:** Cryptographic algorithms used to generate the digital signatures in TLS certificates (such as `RSA` and `ECDSA`).

As explained in our [blog post ↗](https://blog.cloudflare.com/pq-2025/#already-post-quantum-secure-symmetric-cryptography), symmetric ciphers are already post-quantum secure, which means there are two migrations left to occur.

### Hybrid key agreement

With TLS 1.3, [X25519 ↗](https://en.wikipedia.org/wiki/Curve25519) \- an Elliptic Curve Diffie-Hellman (ECDH) protocol - is the most commonly used algorithm in key agreement. However, its security can be broken by quantum computers using [Shor's algorithm ↗](https://en.wikipedia.org/wiki/Shor%27s%5Falgorithm).

It is urgent to migrate key agreement to post-quantum algorithms as soon as possible. The objective is to protect against an adversary capable of harvesting today's encrypted communications and storing it until some time in the future when they can gain access to a sufficiently powerful quantum computer to decrypt it.

In response to this, Cloudflare is an early adopter of ML-KEM, the post-quantum key agreement selected by the US National Institute of Standards and Technology (NIST). For a detailed timeline and more background information refer to [State of the post-quantum Internet in 2025 ↗](https://blog.cloudflare.com/pq-2025/).

Cloudflare has deployed the following hybrid key agreements:

* [X25519MLKEM768 ↗](https://datatracker.ietf.org/doc/draft-kwiatkowski-tls-ecdhe-mlkem/) (Recommended)  
   * TLS identifier: `0x11ec`
* [X25519Kyber768Draft00 ↗](https://datatracker.ietf.org/doc/draft-tls-westerbaan-xyber768d00/) (Obsolete)  
   * TLS identifier: `0x6399`

A hybrid key agreement lays the groundwork as more and more [clients](#1-visitor-to-cloudflare) adopt post-quantum cryptography, while also maintaining the current security provided by X25519\. It is a safer path in case of an unexpected breakthrough that renders all variants of ML-KEM insecure.

### Post-quantum signatures

Recent advances in quantum hardware and algorithms have accelerated the timeline on which a cryptographically relevant quantum computer might exist, which in turn elevates the priority of migrating authentication (signatures) to post-quantum algorithms. Refer to [Cloudflare targets 2029 for full post-quantum security ↗](https://blog.cloudflare.com/post-quantum-roadmap/) for context.

Cloudflare is an early adopter of [ML-DSA ↗](https://csrc.nist.gov/pubs/fips/204/final), the post-quantum digital signature algorithm selected by NIST (FIPS 204), and is beginning to roll out support for ML-DSA in selected product surfaces. Software support for specific schemes is tracked on the [PQC support](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-support/) page.

For background on the post-quantum signature landscape, refer to [A look at the latest post-quantum signature standardization candidates ↗](https://blog.cloudflare.com/another-look-at-pq-signatures/).

## Three connections in the life of a request

flowchart LR
        accTitle: Three connections - from visitor to Cloudflare to origin server
        accDescr: Diagram showing connections for an uncached request.
        A[Visitor]
        subgraph Cloudflare
        X[(Cloudflare <br />service A)]
				B[(Cloudflare <br />service B)]
        end
        C[(Origin server)]

        A --1--> X
				X --2--> B
        B --3--> C

### 1\. Visitor to Cloudflare

As of [October 2022 ↗](https://blog.cloudflare.com/post-quantum-for-all/), all websites and APIs served through Cloudflare over TLS 1.3 support post-quantum hybrid key agreement. However, the connection is only post-quantum secured if the client also supports PQC.

Refer to [Post-quantum cryptography support](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-support/) for a list of browsers and other clients that are compatible with hybrid key agreements.

### 2\. Internal connections

As announced in [September 2023 ↗](https://blog.cloudflare.com/post-quantum-cryptography-ga/), most internal connections for Cloudflare's products and systems have been upgraded to use PQC.

### 3\. Cloudflare to your origin

Finally, Cloudflare also supports [hybrid key agreements](#hybrid-key-agreement) when connecting to origins. In this case, post-quantum secured connections will depend on the origin servers also supporting PQC. Customers can also configure connections to origin servers via [PQ Cloudflare Tunnel](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-and-zero-trust/).

Refer to [Post-quantum cryptography between Cloudflare and origin servers](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-to-origin/) for details.

## Protect corporate network traffic

With [Zero Trust](https://developers.cloudflare.com/cloudflare-one/), Cloudflare allows organizations to upgrade their sensitive network traffic to PQC without the hassle of individually upgrading each and every corporate application, system, or network connection. This includes post-quantum [Cloudflare IPsec](https://developers.cloudflare.com/cloudflare-wan/reference/gre-ipsec-tunnels/) tunnels with both the [Cloudflare One Appliance](https://developers.cloudflare.com/cloudflare-wan/configuration/appliance/) and validated third-party devices. [Cisco ↗](https://www.cisco.com/) and [Fortinet ↗](https://www.fortinet.com/) are the first third-party vendors validated to interoperate with Cloudflare IPsec for post-quantum key agreement — refer to [Tested third-party vendor interoperability](https://developers.cloudflare.com/cloudflare-wan/reference/gre-ipsec-tunnels/#tested-third-party-vendor-interoperability) for the current list. For details on the Cloudflare One configurations, refer to [Post-quantum cryptography in Cloudflare's Zero Trust platform](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-and-zero-trust/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/post-quantum-cryptography/","name":"Post-quantum cryptography (PQC)"}}]}
```

---

---
title: Post-quantum cryptography in Cloudflare One
description: Use post-quantum cryptography with Cloudflare One on-ramps and off-ramps.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Post-quantum cryptography in Cloudflare One

[Cloudflare One](https://developers.cloudflare.com/cloudflare-one/) replaces legacy corporate security perimeters with Cloudflare's global network, making access to the Internet and to corporate resources faster and safer for teams around the world.

Organizations can obtain end-to-end post-quantum encryption of their private network traffic by sending it over Cloudflare One's post-quantum on-ramps and off-ramps. This protects traffic against [harvest-now, decrypt-later ↗](https://en.wikipedia.org/wiki/Harvest%5Fnow,%5Fdecrypt%5Flater) attacks even if the individual applications are not yet upgraded to post-quantum encryption.

Post-quantum encryption is offered in all major Cloudflare One network configurations, including the following on-ramps:

* Agentless [browser access to Cloudflare-proxied applications](#agentless-cloudflare-access) (including self-hosted apps behind Cloudflare Access)
* Agentless [browser on-ramp to Cloudflare Gateway](#secure-web-gateway) via [proxy endpoints](https://developers.cloudflare.com/cloudflare-one/networks/resolvers-and-proxies/proxy-endpoints/)
* [Cloudflare One Client](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/cloudflare-one-client/) (on the end-user device)
* [Cloudflare IPsec](https://developers.cloudflare.com/cloudflare-wan/reference/gre-ipsec-tunnels/) on-ramp

And off-ramps:

* [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/) off-ramp (using `cloudflared`)
* Cloudflare IPsec off-ramp

For traffic that egresses to the public Internet, [Cloudflare Gateway](https://developers.cloudflare.com/cloudflare-one/traffic-policies/http-policies/) also provides post-quantum encryption as a Secure Web Gateway (SWG).

These on-ramps and off-ramps all use [hybrid post-quantum key agreement](https://developers.cloudflare.com/ssl/post-quantum-cryptography/#hybrid-key-agreement).

![Overview diagram of post-quantum Cloudflare One network configurations showing on-ramps and off-ramps](https://developers.cloudflare.com/_astro/pqc-cloudflare-one-overview.CrgyHBvK_1Roi0u.webp) 

The sample configurations below illustrate how Cloudflare One's post-quantum on-ramps and off-ramps fit together for several common use cases. For the broader status of post-quantum support across all Cloudflare products and connections, refer to [PQC in Cloudflare products](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-cloudflare-products/).

## Browser to self-hosted application

A common configuration is browser access to a [self-hosted application](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app/) that is exposed to Cloudflare's network via a [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/). This is often combined with [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/access-controls/policies/) for identity-based policy enforcement; refer to the [agentless access learning path](https://developers.cloudflare.com/learning-paths/clientless-access/initial-setup/) for guidance.

Even if the application itself has not yet migrated to post-quantum cryptography, traffic to it will be protected against harvest-now, decrypt-later attacks.

![Diagram of how post-quantum cryptography works for browser-based access to a self-hosted application via Cloudflare Tunnel](https://developers.cloudflare.com/_astro/pqc-clientless-access.DXk-bG1f_V78if.webp) 

Here is how it works today:

**1\. Connection via browser**

As long as the end user uses a [modern web browser that supports post-quantum key agreement](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-support/#browsers), the connection from the device to Cloudflare's network is secured via TLS 1.3 with post-quantum key agreement.

**2\. Within Cloudflare's global network**

If the user and origin server are geographically distant, then the user's traffic will enter Cloudflare's global network in one geographic location (such as Frankfurt), and exit at another (such as San Francisco). As this traffic moves from one data center to another inside Cloudflare's global network, these hops through the network are secured via TLS 1.3 with post-quantum key agreement.

**3\. Cloudflare Tunnel**

Customers establish a [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/) from their data center or public cloud — where their corporate web application is hosted — to Cloudflare's network. This tunnel is secured using TLS 1.3 with post-quantum key agreement.

This configuration provides end-to-end post-quantum protection for browser access to corporate HTTPS applications without requiring customers to upgrade the security of the applications themselves.

## Cloudflare One Client

[Cloudflare One Client](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/cloudflare-one-client/) (formerly WARP) tunnels traffic from the end-user device to Cloudflare's global network. The following is an example network configuration with a Cloudflare One Client on-ramp and a Cloudflare Tunnel off-ramp.

![Diagram of post-quantum network configuration using Cloudflare One Client on-ramp and Cloudflare Tunnel off-ramp](https://developers.cloudflare.com/_astro/pqc-cloudflare-one-client.pe3Q9Nr9_24LYKc.webp) 

_Note: Labels in this image may reflect a previous product name._

**1\. Connection via Cloudflare One Client**

The Cloudflare One Client uses the MASQUE protocol to connect from the device to Cloudflare's global network, using TLS 1.3 with hybrid ML-KEM.

**2\. Within Cloudflare's global network**

The traffic then travels across Cloudflare's global network over TLS 1.3 with hybrid ML-KEM.

**3\. Cloudflare Tunnel**

[Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/) supports post-quantum key agreement.

With this network configuration, traffic is encapsulated in tunnels protected with post-quantum encryption without requiring individual upgrades of networks or applications. This provides comprehensive protection for any protocol that can be sent through these tunnels, not just for HTTPS.

## Cloudflare IPsec

The following is a sample network configuration that uses the Cloudflare One Client on-ramp to connect an end-user device to a server behind a [Cloudflare One Appliance](https://developers.cloudflare.com/cloudflare-wan/configuration/appliance/) off-ramp. Traffic to the server is protected by post-quantum cryptography as it travels over the public Internet, even if the server itself does not support post-quantum cryptography.

![Diagram of post-quantum network configuration using Cloudflare One Client on-ramp to Cloudflare One Appliance off-ramp](https://developers.cloudflare.com/_astro/pqc-cloudflare-ipsec.5IiyHdoZ_Z94W71.webp) 

**1\. Connection via Cloudflare One Client**

The Cloudflare One Client uses the MASQUE protocol, as described in the [Cloudflare One Client](#cloudflare-one-client) section above.

**2\. Within Cloudflare's global network**

The traffic then travels across Cloudflare's global network over TLS 1.3 with hybrid ML-KEM.

**3\. Cloudflare IPsec with Cloudflare One Appliance**

Traffic leaves the Cloudflare network over a post-quantum Cloudflare IPsec link that is terminated at a Cloudflare One Appliance. The Cloudflare One Appliance uses a non-IKE keying protocol built into the control plane, secured with TLS, that establishes the keys used to encrypt dataplane traffic in the IPsec ESP protocol. From Appliance version 2026.2.0, the control plane establishes keys over TLS 1.3 protected with hybrid ML-KEM.

## Cloudflare IPsec with third-party devices

[Cloudflare IPsec](https://developers.cloudflare.com/cloudflare-wan/reference/gre-ipsec-tunnels/) also supports post-quantum key agreement with compatible third-party network devices using standard IKEv2\. This extends post-quantum protection to organizations that connect their own routers and firewalls to Cloudflare's global network instead of using the Cloudflare One Appliance.

The hybrid key agreement is negotiated using ML-KEM as an additional Key Exchange to classical Diffie-Hellman during the IKEv2 handshake, as defined in [RFC 9370 ↗](https://datatracker.ietf.org/doc/rfc9370/) and [draft-ietf-ipsecme-ikev2-mlkem ↗](https://datatracker.ietf.org/doc/draft-ietf-ipsecme-ikev2-mlkem/). For the list of validated third-party platforms and their supported parameters, refer to [Tested third-party vendor interoperability](https://developers.cloudflare.com/cloudflare-wan/reference/gre-ipsec-tunnels/#tested-third-party-vendor-interoperability).

## Secure Web Gateway

A [secure web gateway (SWG) ↗](https://www.cloudflare.com/learning/access-management/what-is-a-secure-web-gateway/) is used to secure access to third-party websites on the public Internet by intercepting and inspecting TLS traffic.

[Cloudflare Gateway](https://developers.cloudflare.com/cloudflare-one/traffic-policies/http-policies/) [supports post-quantum cryptography for HTTPS traffic](https://developers.cloudflare.com/cloudflare-one/traffic-policies/http-policies/tls-decryption/#post-quantum-support). As long as the third-party website that is being inspected supports post-quantum key agreement, Cloudflare's SWG also supports post-quantum key agreement.

![Diagram of how post-quantum cryptography works with Cloudflare's Secure Web Gateway](https://developers.cloudflare.com/_astro/pqc-secure-web-gateway.Br-ATUfe_146I1p.webp) 

Cloudflare Gateway's HTTPS filtering feature involves two post-quantum TLS connections, as follows:

**1\. Connection from the client to Gateway**

A [modern web browser that supports post-quantum key agreement](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-support/#browsers) connects to Gateway via the [Agentless via proxy endpoints](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-cloudflare-products/#agentless-via-proxy-endpoints) on-ramp. The connection is secured by TLS 1.3 with post-quantum key agreement.

The [Cloudflare One Client](#cloudflare-one-client) and [Cloudflare IPsec](#cloudflare-ipsec) on-ramps described in the sections above can also route traffic to Gateway with post-quantum protection.

**2\. Connection from Gateway to the origin server**

A TLS connection is initiated from a data center in Cloudflare's network to the origin server, which is typically controlled by a third party. The connection from Cloudflare's SWG supports post-quantum key agreement, as long as the third-party origin server also supports post-quantum key agreement. You can test this out by using [https://pq.cloudflareresearch.com/ ↗](https://pq.cloudflareresearch.com/) as your third-party origin server.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/post-quantum-cryptography/","name":"Post-quantum cryptography (PQC)"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/post-quantum-cryptography/pqc-and-zero-trust/","name":"Post-quantum cryptography in Cloudflare One"}}]}
```

---

---
title: PQC in Cloudflare products
description: Track which Cloudflare products support post-quantum key agreement and post-quantum signatures.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# PQC in Cloudflare products

Cloudflare is [targeting 2029 ↗](https://blog.cloudflare.com/post-quantum-roadmap/) to be fully post-quantum secure across its entire product suite.

This page shows the status of the migration. Each section below groups Cloudflare products by the underlying secure communication channel. Once a channel supports PQC, every product built on top inherits PQC support.

Each section captures the classes of post-quantum algorithms deployed in the secure communication channel: [key agreement](https://developers.cloudflare.com/ssl/post-quantum-cryptography/#hybrid-key-agreement) (sometimes called post-quantum encryption, which protects against [harvest-now, decrypt-later ↗](https://en.wikipedia.org/wiki/Harvest%5Fnow,%5Fdecrypt%5Flater) attacks) and [signatures](https://developers.cloudflare.com/ssl/post-quantum-cryptography/#post-quantum-signatures) (sometimes called post-quantum authentication, which protects live systems against unauthorized access by quantum adversaries [after Q-Day ↗](https://blog.cloudflare.com/post-quantum-roadmap/)).

A Cloudflare-side ✅ entry only delivers end-to-end post-quantum protection when **the party on the other side of the connection also supports the same post-quantum algorithms**. Refer to [PQC support](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-support/) for the list of browsers, libraries, and servers that support the algorithms Cloudflare has deployed.

For an end-to-end walkthrough of how Cloudflare One on-ramps and off-ramps fit together, refer to [PQC and Cloudflare One](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-and-zero-trust/).

## Visitor to Cloudflare

Inbound TLS 1.3 (including QUIC) from end-user clients to Cloudflare's edge.

| Protection    | Status                                                                                                             |
| ------------- | ------------------------------------------------------------------------------------------------------------------ |
| Key agreement | ✅ X25519MLKEM768                                                                                                   |
| Signatures    | 📝 Planned via [Merkle Tree Certificates ↗](https://datatracker.ietf.org/doc/draft-ietf-plants-merkle-tree-certs/) |

Reference: [PQC for all websites and APIs ↗](https://blog.cloudflare.com/post-quantum-for-all/).

**Products covered:** any proxied hostname or HTTPS application behind Cloudflare, including:

* The Cloudflare developer platform: [Workers](https://developers.cloudflare.com/workers/) custom domains, `*.workers.dev`, [Pages](https://developers.cloudflare.com/pages/), [R2](https://developers.cloudflare.com/r2/) public buckets, [Stream](https://developers.cloudflare.com/stream/), and [Images](https://developers.cloudflare.com/images/).
* [API Shield](https://developers.cloudflare.com/api-shield/)\-protected APIs.
* The Cloudflare API and dashboard.
* [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app/) self-hosted applications (browser-to-edge leg).

This section only covers the inbound TLS connection from the end-user client to Cloudflare's edge. When a Worker fetches data from a backend storage service ([D1](https://developers.cloudflare.com/d1/), [KV](https://developers.cloudflare.com/kv/), [Durable Objects](https://developers.cloudflare.com/durable-objects/), [R2](https://developers.cloudflare.com/r2/), [Workers AI](https://developers.cloudflare.com/workers-ai/), [Hyperdrive](https://developers.cloudflare.com/hyperdrive/), and similar), that connection is governed by the [Cloudflare internal network](#cloudflare-internal-network) section. When a Worker calls out to a third-party origin via `fetch()`, it is governed by the [Cloudflare to origin](#cloudflare-to-origin) section. The [Agentless via proxy endpoints](#agentless-via-proxy-endpoints) on-ramp to Cloudflare Gateway terminates inbound TLS in its own edge stack and is covered separately below.

## Cloudflare internal network

Service-to-service TLS connections between Cloudflare data centers and internal services.

| Protection    | Status            |
| ------------- | ----------------- |
| Key agreement | 🚧 X25519MLKEM768 |
| Signatures    | Not yet           |

Reference: [PQC generally available ↗](https://blog.cloudflare.com/post-quantum-cryptography-ga/), [Roadmap ↗](https://blog.cloudflare.com/post-quantum-roadmap/).

Most internal connections have been migrated to X25519MLKEM768\. A long tail of services is still in the process of being upgraded.

## Cloudflare to origin

Outbound TLS 1.3 connections from Cloudflare's edge to customer origin servers.

| Protection    | Status           |
| ------------- | ---------------- |
| Key agreement | ✅ X25519MLKEM768 |
| Signatures    | Not yet          |

Reference: [PQC to your origin](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-to-origin/).

**Products covered:** any Cloudflare-proxied zone's origin pull, and the egress leg of [Cloudflare Gateway](#cloudflare-gateway) (SWG, HTTPS inspection) when Gateway fetches third-party origin content on behalf of the client. Gateway's post-quantum support on this leg is independent of which on-ramp the client uses to reach Cloudflare.

Note

If your origin server does not yet support PQC, you can onboard it to Cloudflare's network with a PQC connection by putting it behind [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/).

## Cloudflare Tunnel

Outbound TLS 1.3 tunnel from `cloudflared` on a customer origin to Cloudflare's global network.

| Protection    | Status           |
| ------------- | ---------------- |
| Key agreement | ✅ X25519MLKEM768 |
| Signatures    | Not yet          |

Reference: [PQ Cloudflare Tunnel ↗](https://blog.cloudflare.com/post-quantum-tunnel/), [PQC and Cloudflare One](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-and-zero-trust/).

**Products covered:** [Workers VPC](https://developers.cloudflare.com/workers-vpc/) private-network access and any [Cloudflare One](https://developers.cloudflare.com/cloudflare-one/) off-ramp that egresses via `cloudflared` (for example, [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app/) self-hosted applications).

## Cloudflare One

The sections below cover the connections and services that make up [Cloudflare One](https://developers.cloudflare.com/cloudflare-one/). For an end-to-end walkthrough of how on-ramps and off-ramps fit together, refer to [PQC and Cloudflare One](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-and-zero-trust/).

### Cloudflare One Client

MASQUE tunnel (TLS 1.3) from an end-user device to Cloudflare's global network, established by the [Cloudflare One Client](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/cloudflare-one-client/) (formerly WARP).

| Protection    | Status           |
| ------------- | ---------------- |
| Key agreement | ✅ X25519MLKEM768 |
| Signatures    | Not yet          |

Reference: [PQC and Cloudflare One: Cloudflare One Client](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-and-zero-trust/#cloudflare-one-client).

This connection also serves as a post-quantum on-ramp for traffic that traverses [Cloudflare Gateway](#cloudflare-gateway).

### Cloudflare Mesh

[Cloudflare Mesh](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-mesh/) provides private IP connectivity between devices and servers using the Cloudflare One Client on each Mesh node and client device.

Mesh inherits its post-quantum protection from the [Cloudflare One Client](#cloudflare-one-client) connection, which is used as both the on-ramp and the off-ramp for Mesh traffic.

### Cloudflare Gateway

[Cloudflare Gateway](https://developers.cloudflare.com/cloudflare-one/traffic-policies/http-policies/tls-decryption/#post-quantum-support) is a Secure Web Gateway that runs on Cloudflare's edge and filters HTTPS traffic egressing to the public Internet. Gateway has no client-side component; clients reach Gateway via one of several post-quantum on-ramps:

* The [Cloudflare One Client](#cloudflare-one-client).
* A [Cloudflare IPsec](#cloudflare-ipsec) tunnel.
* The [Agentless via proxy endpoints](#agentless-via-proxy-endpoints) on-ramp.

The egress leg from Gateway to third-party origin servers is covered by [Cloudflare to origin](#cloudflare-to-origin) and is independent of the on-ramp.

Reference: [PQC and Cloudflare One: Secure Web Gateway](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-and-zero-trust/#secure-web-gateway).

### Agentless via proxy endpoints

Cloudflare Gateway [proxy endpoints](https://developers.cloudflare.com/cloudflare-one/networks/resolvers-and-proxies/proxy-endpoints/) let browsers route their egress HTTPS traffic through Cloudflare Gateway for inspection and filtering, without an agent installed on the device. Browsers are configured via a Proxy Auto-Configuration (PAC) file or system proxy settings to forward traffic to a Cloudflare-hosted proxy endpoint, which terminates TLS at Cloudflare's edge.

| Protection    | Status           |
| ------------- | ---------------- |
| Key agreement | ✅ X25519MLKEM768 |
| Signatures    | Not yet          |

Reference: [Proxy endpoints](https://developers.cloudflare.com/cloudflare-one/networks/resolvers-and-proxies/proxy-endpoints/), [PQC and Cloudflare One: Secure Web Gateway](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-and-zero-trust/#secure-web-gateway).

### Cloudflare IPsec

IKEv2 key exchange for IPsec tunnels between third-party branch connectors and Cloudflare's global network.

| Protection    | Status                                           |
| ------------- | ------------------------------------------------ |
| Key agreement | ✅ ML-KEM-768/1024 + DH Group 20 (P-384) in IKEv2 |
| Signatures    | Not yet                                          |

Reference: [PQC SASE ↗](https://blog.cloudflare.com/post-quantum-sase/), [GRE and IPsec tunnels](https://developers.cloudflare.com/cloudflare-wan/reference/gre-ipsec-tunnels/#tested-third-party-vendor-interoperability), [draft-ietf-ipsecme-ikev2-mlkem ↗](https://datatracker.ietf.org/doc/draft-ietf-ipsecme-ikev2-mlkem/).

The IPsec ESP dataplane can alternatively be keyed using the [Cloudflare One Appliance](#cloudflare-one-appliance) control plane instead of IKEv2.

### Cloudflare One Appliance

TLS 1.3 control-plane connection used by the [Cloudflare One Appliance](https://developers.cloudflare.com/cloudflare-wan/configuration/appliance/reference/) (formerly Magic WAN Connector) to establish keys for its IPsec ESP dataplane tunnels.

| Protection    | Status           |
| ------------- | ---------------- |
| Key agreement | ✅ X25519MLKEM768 |
| Signatures    | Not yet          |

Reference: [PQC SASE ↗](https://blog.cloudflare.com/post-quantum-sase/), [Cloudflare One Appliance](https://developers.cloudflare.com/cloudflare-wan/configuration/appliance/reference/), [PQC and Cloudflare One](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-and-zero-trust/#cloudflare-ipsec).

## Contributing

This listing is maintained alongside the rest of the Cloudflare SSL/TLS documentation. If you spot an inaccuracy or have an update after a product announcement, [contributions](https://developers.cloudflare.com/style-guide/contributions/) are welcome.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/post-quantum-cryptography/","name":"Post-quantum cryptography (PQC)"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/post-quantum-cryptography/pqc-cloudflare-products/","name":"PQC in Cloudflare products"}}]}
```

---

---
title: PQC support
description: Consider information about post-quantum cryptography at Cloudflare - deployed key agreements, signatures, and software support.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# PQC support

The sections below summarize third-party software support for the post-quantum algorithms Cloudflare has deployed, organized by software category. [Contributions](https://developers.cloudflare.com/style-guide/contributions/) to keep the listing up-to-date are welcome.

Two classes of algorithm are tracked:

* **Key agreement** — the [X25519MLKEM768 ↗](https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/) hybrid, which protects against [harvest-now-decrypt-later ↗](https://en.wikipedia.org/wiki/Harvest%5Fnow,%5Fdecrypt%5Flater) attacks on encrypted traffic. Refer to [hybrid key agreement](https://developers.cloudflare.com/ssl/post-quantum-cryptography/#hybrid-key-agreement) for background.
* **Signatures** — [ML-DSA ↗](https://csrc.nist.gov/pubs/fips/204/final), the post-quantum digital signature algorithm standardized by NIST. Defined with three parameter sets (ML-DSA-44, ML-DSA-65, ML-DSA-87), of which **ML-DSA-44 is the variant Cloudflare is currently evaluating for deployment**. Refer to [post-quantum signatures](https://developers.cloudflare.com/ssl/post-quantum-cryptography/#post-quantum-signatures) for background.

Warning

The listings below are for reference only. Responsibility for third-party software lies with their respective maintainers. Use them at your own discretion.

## Browsers

Browsers are grouped by the underlying rendering engine and TLS stack. Browsers sharing an engine generally share the same post-quantum support, but derivative browsers can lag the upstream engine or disable post-quantum features by policy. Verify behavior in the specific browser version you care about before assuming derivative support. [Cloudflare Radar's browser support check ↗](https://radar.cloudflare.com/post-quantum#browser-support) is a quick way to confirm whether a given browser negotiates post-quantum key agreement with Cloudflare.

### Chromium-based (BoringSSL)

#### Brave

* **Key agreement:** ✅ Default in Brave 1.73.86+ (Chromium 131)
* **Signatures:** Not yet
* **Reference:** [Brave ↗](https://brave.com)

#### Chrome

* **Key agreement:** ✅ Default in Chrome 131+
* **Signatures:** 📝 Planned via [Merkle Tree Certificates ↗](https://datatracker.ietf.org/doc/draft-ietf-plants-merkle-tree-certs/)
* **Reference:** [Chrome ↗](https://www.google.com/chrome/), [Cultivating a robust and efficient quantum-safe HTTPS ↗](https://security.googleblog.com/2026/02/cultivating-robust-and-efficient.html)

Chrome is not planning to add standard X.509 post-quantum certificates to the public Chrome Root Store. Instead, Chrome is developing MTCs in the IETF PLANTS working group, currently in a feasibility study phase with Cloudflare.

#### Edge

* **Key agreement:** ✅ Default in Edge 131+
* **Signatures:** Not yet
* **Reference:** [Edge ↗](https://microsoft.com/edge/)

#### Opera

* **Key agreement:** ✅ Default in Opera 116+ (Chromium 131)
* **Signatures:** Not yet
* **Reference:** [Opera ↗](https://opera.com)

### Gecko-based (Firefox / NSS)

#### Firefox

* **Key agreement:** ✅ Default in Firefox 132+ (Desktop), 145+ (Android)
* **Signatures:** Not yet
* **Reference:** [Firefox ↗](https://www.mozilla.org/firefox/)

For QUIC/HTTP3, Firefox 135+ (Desktop).

#### Tor Browser

* **Key agreement:** ✅ Default in Tor Browser 15.0+
* **Signatures:** Not yet
* **Reference:** [Tor Browser ↗](https://www.torproject.org/)

Based on Firefox ESR with additional hardening.

### WebKit-based (Safari)

#### Safari

* **Key agreement:** ✅ Default in Safari 26+
* **Signatures:** Not yet
* **Reference:** [Safari ↗](https://www.apple.com/safari/)

System-wide in iOS 26, macOS Tahoe 26, and other [Apple operating systems ↗](https://support.apple.com/122756).

## Libraries

This section splits into the foundational native libraries (written in C/C++) and the language bindings and higher-level libraries that build on top of them.

### Native libraries

#### AWS-LC

* **Key agreement:** ✅
* **Signatures:** ✅
* **Reference:** [aws-lc ↗](https://github.com/aws/aws-lc), [Post-Quantum Cryptography in AWS-LC ↗](https://github.com/aws/aws-lc/blob/main/crypto/fipsmodule/PQREADME.md)

ML-KEM-512/768/1024 and hybrids `X25519MLKEM768`, `SecP256r1MLKEM768`, `SecP384r1MLKEM1024`; ML-DSA-44/65/87.

#### BoringSSL

* **Key agreement:** ✅
* **Signatures:** ✅
* **Reference:** [BoringSSL ↗](https://boringssl.googlesource.com/boringssl/)

ML-DSA-44/65/87.

#### Botan C++

* **Key agreement:** ✅ Default in TLS since 3.7.0
* **Signatures:** ✅ 3.6.0+
* **Reference:** [Botan ↗](https://botan.randombit.net/)

ML-DSA-44/65/87.

#### GnuTLS

* **Key agreement:** ✅ 3.8.9+ compiled with leancrypto 1.2.0+ (or 3.8.8–3.8.9 with liboqs 0.11.0+)
* **Signatures:** ✅ 3.8.10+ — usable in TLS handshakes
* **Reference:** [GnuTLS ↗](https://www.gnutls.org)

Hybrids `X25519MLKEM768` and `SecP256r1MLKEM768` from 3.8.8+; `SecP384r1MLKEM1024` added in 3.8.9+. ML-DSA-44/65/87.

#### OpenSSL

* **Key agreement:** ✅ Default in 3.5.0+
* **Signatures:** ✅ 3.5.0+
* **Reference:** [OpenSSL ↗](https://www.openssl.org/)

Hybrid `X25519MLKEM768` in 3.5.0+; `SecP256r1MLKEM768` and `curveSM2MLKEM768` added in 3.6.0+. ML-DSA-44/65/87.

#### Open Quantum Safe

* **Key agreement:** ✅ liboqs 0.10.0+, oqs-provider 0.7.0+
* **Signatures:** ✅ liboqs 0.14.0+, oqs-provider 0.9.0+
* **Reference:** [Open Quantum Safe ↗](https://openquantumsafe.org/)

Reference implementations, not recommended for production.

#### s2n-tls

* **Key agreement:** ✅
* **Signatures:** Not yet
* **Reference:** [s2n-tls ↗](https://github.com/aws/s2n-tls)

AWS's open-source TLS implementation built on [AWS-LC](#aws-lc).

### Language bindings and higher-level libraries

#### aws-lc-rs (Rust)

* **Key agreement:** ✅
* **Signatures:** 🚧 Behind `unstable` feature
* **Reference:** [aws-lc-rs ↗](https://crates.io/crates/aws-lc-rs)

Rust bindings around [AWS-LC](#aws-lc); underlies [rustls-post-quantum](#rustls-post-quantum-rust)'s ML-DSA support. ML-KEM via [aws-lc-rs::kem ↗](https://docs.rs/aws-lc-rs/latest/aws%5Flc%5Frs/kem/); ML-DSA-44/65/87 via [unstable::signature ↗](https://docs.rs/aws-lc-rs/latest/aws%5Flc%5Frs/unstable/signature/).

#### CIRCL (Cloudflare)

* **Key agreement:** ✅
* **Signatures:** ✅ 1.5.0+ via [sign/mldsa ↗](https://github.com/cloudflare/circl/tree/main/sign/mldsa)
* **Reference:** [CIRCL ↗](https://github.com/cloudflare/circl)

Pure-Go cryptographic primitives library. ML-KEM-512/768/1024 and ML-DSA-44/65/87.

#### Go

* **Key agreement:** ✅ Default in Go 1.24+
* **Signatures:** 🚧 Internal implementation in Go 1.26; public [crypto/mldsa ↗](https://github.com/golang/go/issues/77626) proposed for Go 1.27
* **Reference:** [Go ↗](https://go.dev)

Cloudflare's [fork of Go ↗](https://github.com/cloudflare/go) also supports key agreement via [CIRCL](#circl-cloudflare).

#### Java (OpenJDK)

* **Key agreement:** ✅ Default in Java 27+ ([JEP 527 ↗](https://openjdk.org/jeps/527))
* **Signatures:** 🚧 Java 24+ provides ML-DSA APIs ([JEP 497 ↗](https://openjdk.org/jeps/497)) but they are not yet integrated into `javax.net.ssl` TLS
* **Reference:** [OpenJDK ↗](https://openjdk.org/)

#### Node.js

* **Key agreement:** ✅ Default in 24.5.0+ and 22.20.0+ ([backported ↗](https://nodejs.org/en/blog/release/v22.20.0#openssl-updated-to-352))
* **Signatures:** ✅ 24.5.0+
* **Reference:** [Node.js ↗](https://nodejs.org/)

Uses bundled [OpenSSL](#openssl) 3.5\. ML-DSA-44/65/87.

#### RustCrypto (Rust)

* **Key agreement:** ✅ [ml-kem ↗](https://crates.io/crates/ml-kem)
* **Signatures:** ✅ [ml-dsa ↗](https://crates.io/crates/ml-dsa)
* **Reference:** [RustCrypto ↗](https://github.com/RustCrypto)

Pure-Rust crates, independent of [AWS-LC](#aws-lc). ML-DSA-44/65/87.

#### rustls (Rust)

* **Key agreement:** ✅ Enabled by default since rustls 0.23.27
* **Signatures:** 🚧 Unstable
* **Reference:** [rustls ↗](https://crates.io/crates/rustls)

TLS library built on top of [rustls-post-quantum](#rustls-post-quantum-rust).

#### rustls-post-quantum (Rust)

* **Key agreement:** ✅ `X25519MLKEM768`
* **Signatures:** 🚧 Unstable ML-DSA support (behind `aws-lc-rs-unstable` feature)
* **Reference:** [rustls-post-quantum ↗](https://crates.io/crates/rustls-post-quantum)

Extension crate for [rustls](#rustls-rust) that provides post-quantum algorithms using [aws-lc-rs](#aws-lc-rs-rust) under the hood.

#### Zig

* **Key agreement:** ✅ Zig 0.14.0+ (client)
* **Signatures:** Not yet
* **Reference:** [Zig ↗](https://ziglang.org/)

## Servers

### Caddy

* **Key agreement:** ✅ Default in Caddy 2.10.0+
* **Signatures:** Blocked on Go `crypto/mldsa`
* **Reference:** [Caddy ↗](https://caddyserver.com/)

### NGINX

* **Key agreement:** ✅ Default when compiled with OpenSSL 3.5+ ([instructions ↗](https://github.com/nginx/nginx/issues/288))
* **Signatures:** ✅ When compiled with OpenSSL 3.5+
* **Reference:** [NGINX ↗](https://github.com/nginx/nginx)

### rpxy

* **Key agreement:** ✅ Default in 0.9.4+
* **Signatures:** Blocked on Rust PQ signature support
* **Reference:** [rpxy ↗](https://github.com/junkurihara/rust-rpxy)

### Traefik

* **Key agreement:** ✅ Default in 3.4.2+, 2.11.26+ ([commit ↗](https://github.com/traefik/traefik/commit/cd16321dd9c25bb47a2e9417b2a4a75959be63d0)); configurable via `curvePreferences` in 3.5.0-rc.1+
* **Signatures:** Blocked on Go `crypto/mldsa`
* **Reference:** [Traefik ↗](https://traefik.io/traefik/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/post-quantum-cryptography/","name":"Post-quantum cryptography (PQC)"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/post-quantum-cryptography/pqc-support/","name":"PQC support"}}]}
```

---

---
title: Post-quantum between Cloudflare and origin servers
description: Learn about post-quantum cryptography in connections from Cloudflare to your origin servers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Post-quantum between Cloudflare and origin servers

As explained in [About PQC](https://developers.cloudflare.com/ssl/post-quantum-cryptography/), Cloudflare has deployed support for hybrid key agreements, which includes both the most common key agreement for TLS 1.3, X25519, and the post-quantum secure ML-KEM.

With X25519, the [ClientHello ↗](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/) almost always fits within one network packet. However, with the addition of ML-KEM, the ClientHello is typically split across two packets.

This poses a question of how the origin servers - as well as other middleboxes (routers, load balancers, etc) - will handle this change in behavior. Although allowed by the TLS 1.3 standard ([RFC 8446 ↗](https://www.rfc-editor.org/rfc/rfc8446.html)), a split ClientHello risks not being handled well due to [protocol ossification ↗](https://en.wikipedia.org/wiki/Protocol%5Fossification) and implementation bugs. Refer to our [blog post ↗](https://blog.cloudflare.com/post-quantum-to-origins/) for details.

Customers can also configure connections to origin servers via [PQ Cloudflare Tunnel](https://developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-and-zero-trust/).

## ClientHello from Cloudflare

To reduce the risk of any issues when connecting to servers that are not ready for hybrid key agreements, Cloudflare leverages HelloRetryRequest. This means that, instead of sending [X25519MLKEM768](https://developers.cloudflare.com/ssl/post-quantum-cryptography/#hybrid-key-agreement) immediately as a keyshare [1](#user-content-fn-1), Cloudflare will by default only advertise support for it.

If the origin supports post-quantum hybrid key agreement, it can use HelloRetryRequest to request it from Cloudflare.

## Set up

### Cloudflare zone settings

The method described above is the one Cloudflare uses to support post-quantum to all outbound connections. However, if your origin server supports PQC and prefers it, you can use the [API](https://developers.cloudflare.com/api/resources/origin%5Fpost%5Fquantum%5Fencryption/methods/update/) to adjust your Cloudflare zone settings and avoid the extra round trip.

It is also possible to opt out of PQC using the same API endpoint.

Note

This setting affects all outbound connections from the zone you specify in the API call, including `fetch()` requests made by [Workers](https://developers.cloudflare.com/workers/) on your zone.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`
* `Zone Write`

Change Origin Post-Quantum Encryption setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/cache/origin_post_quantum_encryption" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": "<YOUR_CHOSEN_SETTING>"

  }'


```

The possible values are:

* `supported` (most compatible): Advertise support for post-quantum key agreement, but send a classical keyshare in the first ClientHello.
* `preferred` (most performant): Send a post-quantum keyshare in the first ClientHello. Cloudflare continues to advertise support for classical keyshares as well.
* `off`: Do not send nor advertise support for post-quantum key agreement to the origin.

### Origin server

To make sure that your origin server prefers the post-quantum key agreement, use the `bssl` tool of [BoringSSL ↗](https://github.com/google/boringssl):

Terminal window

```

$ bssl client -connect (your server):443 -curves X25519MLKEM768


```

Verify that the `ECDHE curve` in the handshake output indicates `X25519MLKEM768`.

## Footnotes

1. When, to remove a round trip, a client makes a guess of what the server supports. [↩](#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":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/post-quantum-cryptography/","name":"Post-quantum cryptography (PQC)"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/post-quantum-cryptography/pqc-to-origin/","name":"Post-quantum between Cloudflare and origin servers"}}]}
```

---

---
title: Troubleshooting
description: Troubleshoot common SSL/TLS errors and configuration issues.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

For FAQs and other troubleshooting information, refer to the following resources:

Filter resources...

[Troubleshooting client certificates](https://developers.cloudflare.com/ssl/client-certificates/troubleshooting/)[Troubleshooting - Cipher suites — Edge certificates](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/troubleshooting/)[Total TLS error messages](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/error-messages/)[Troubleshooting Domain Control Validation](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/troubleshooting/)[Troubleshooting | Custom certificates](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/troubleshooting/)[Troubleshooting Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/troubleshooting/)[SSL/TLS FAQ](https://developers.cloudflare.com/ssl/faq/)[Troubleshooting Keyless SSL](https://developers.cloudflare.com/ssl/keyless-ssl/troubleshooting/)[Troubleshooting Cloudflare origin CA](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/troubleshooting/)[Cloudflare and CVE-2019-1559](https://developers.cloudflare.com/ssl/reference/cloudflare-and-cve-2019-1559/)[Troubleshoot ERR\_SSL\_PROTOCOL\_ERROR](https://developers.cloudflare.com/ssl/troubleshooting/err-ssl-protocol-error/)[General SSL errors](https://developers.cloudflare.com/ssl/troubleshooting/general-ssl-errors/)[Mixed content errors](https://developers.cloudflare.com/ssl/troubleshooting/mixed-content-errors/)[ERR\_TOO\_MANY\_REDIRECTS](https://developers.cloudflare.com/ssl/troubleshooting/too-many-redirects/)[Fix VERSION\_OR\_CIPHER\_MISMATCH](https://developers.cloudflare.com/ssl/troubleshooting/version-cipher-mismatch/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: ERR_SSL_PROTOCOL_ERROR
description: Learn how to troubleshoot ERR_SSL_PROTOCOL_ERROR and similar SSL/TLS protocol errors when using Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# ERR\_SSL\_PROTOCOL\_ERROR

If visitors to your site experience SSL protocol errors such as:

* `ERR_SSL_PROTOCOL_ERROR` (Chrome)
* `Secure Connection Failed` or `PR_END_OF_FILE_ERROR` (Firefox)
* `Safari can't open the page because it couldn't establish a secure connection to the server` (Safari)

These errors indicate that the SSL/TLS handshake failed. This can happen for many reasons, including certificate issues, protocol incompatibilities, or network interference.

## Rule out common causes first

Before investigating protocol-specific issues, verify that the error is not caused by:

* **Certificate not yet active** \- If you recently added your domain, wait for your [Universal SSL certificate to activate](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/troubleshooting/).
* **Multi-level subdomain not covered** \- Universal SSL only covers one level of subdomains. Refer to [ERR\_SSL\_VERSION\_OR\_CIPHER\_MISMATCH](https://developers.cloudflare.com/ssl/troubleshooting/version-cipher-mismatch/#multi-level-subdomains) for solutions.
* **Cipher suite mismatch** \- Older clients may not support modern cipher suites. Refer to [cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/) for configuration options.

---

## Test HTTP/3 (QUIC) compatibility

HTTP/3 uses the QUIC protocol over UDP, which some networks, firewalls, or devices do not fully support. If visitors experience intermittent SSL protocol errors, HTTP/3 may be the cause.

### When to suspect HTTP/3 issues

* Errors occur intermittently, not on every request
* The issue affects only some visitors (often those on corporate networks or certain ISPs)
* Visitors report the site works after refreshing multiple times
* The issue does not occur when using a VPN

### How to test

Temporarily disable HTTP/3 to determine if it is the cause:

1. In the Cloudflare dashboard, go to the **Protocol Optimization** page.[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/speed/optimization)
2. Turn off **HTTP/3 (with QUIC)**.
3. Ask the affected visitor to test again.

If disabling HTTP/3 resolves the issue, the visitor's network likely blocks or mishandles UDP traffic on port 443\. **Re-enable HTTP/3 after testing** and work with the visitor to identify the specific network issue.

---

## Test TLS 1.3 compatibility

TLS 1.3 is the latest version of the TLS protocol and provides improved security and performance. However, some network security devices that perform SSL/TLS inspection may not fully support TLS 1.3.

### When to suspect TLS 1.3 issues

* Visitors using corporate networks with SSL inspection report connection issues
* Antivirus software with HTTPS scanning is installed on the visitor's device
* The error occurs consistently for specific visitors but not others

### How to test

Warning

Disabling TLS 1.3 reduces security for all visitors. Only disable it temporarily for diagnostic purposes.

Temporarily disable TLS 1.3 to determine if it is the cause:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. Find **TLS 1.3** and turn it off.
3. Ask the affected visitor to test again.

If disabling TLS 1.3 resolves the issue, the visitor's network has a middlebox (firewall, proxy, or antivirus) that does not support TLS 1.3\. **Re-enable TLS 1.3 after testing** and ask the visitor to:

* Update their security software to a version that supports TLS 1.3
* Contact their IT department to update network security devices
* Temporarily disable HTTPS scanning in their antivirus software

If you cannot identify the root cause, [contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) with packet captures from the affected visitor showing the failed TLS handshake.

---

## ISP and network interference

Some Internet Service Providers (ISPs) and corporate networks deploy security features that can interfere with HTTPS connections:

* **Deep packet inspection (DPI)** \- Inspects encrypted traffic and may interfere with connections it cannot analyze
* **SSL/TLS interception proxies** \- Intercept and re-encrypt traffic, which can fail with newer protocols
* **Parental controls or content filters** \- May block or interfere with connections to certain sites
* **Carrier-grade NAT (CGNAT)** \- Can cause connection issues, especially with UDP-based protocols like QUIC

### How to identify network interference

Ask the affected visitor to:

1. **Try a different network** \- Use mobile data instead of Wi-Fi, or try a different ISP
2. **Use a VPN** \- If the site works through a VPN, the ISP or local network is likely interfering
3. **Disable local security software** \- Temporarily disable antivirus or firewall software to test
4. **Check with their ISP** \- Some ISPs have security features that can be disabled upon request

### If network interference is confirmed

If the issue is caused by the visitor's ISP or network:

* The visitor may need to contact their ISP to add the domain to an allowlist or disable specific security features
* For corporate networks, the IT department may need to update firewall or proxy rules
* As a site owner, you have limited options since the interference occurs outside of Cloudflare

---

## Collect diagnostic information

If the above steps do not resolve the issue, collect the following information from affected visitors:

1. **Cloudflare diagnostic data** \- Ask the visitor to access `https://your-domain.com/cdn-cgi/trace` and share the output
2. **Exact error message** \- The full error text and error code from the browser
3. **Browser and OS version** \- Including any security software installed
4. **Network information** \- Whether they are on a corporate network, using a VPN, or have any proxy configured

Check [Cloudflare Status ↗](https://www.cloudflarestatus.com/) to verify there are no ongoing incidents affecting SSL/TLS.

If the issue persists and affects many visitors, [contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) with the diagnostic information collected.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/troubleshooting/err-ssl-protocol-error/","name":"ERR_SSL_PROTOCOL_ERROR"}}]}
```

---

---
title: General SSL errors
description: Learn how to troubleshoot various SSL/TLS errors with Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# General SSL errors

## Let's Encrypt chain update

### Symptom

Starting September 9, 2024, visitors that try to connect to your website using older devices - for example, Android 7.0 and earlier - have access problems or reach security warnings.

### Resolution

The fastest way to resolve this issue is to change your certificate to use [Google Trust Services](https://developers.cloudflare.com/ssl/reference/certificate-authorities/#google-trust-services) as the certificate authority.

## Outdated browsers

### Symptom

Until Cloudflare provides an SSL certificate for your domain, the following errors may appear in various browsers for HTTPS traffic:

* **Firefox**: `_ssl_error_bad_cert_domain` / `This connection is untrusted`
* **Chrome**: `Your connection is not private`
* **Safari**: `Safari can't verify the identity of the website`
* **Edge / Internet Explorer**: `There is a problem with this website's security certificate`

### Resolution

Even with a Cloudflare SSL certificate provisioned for your domain, older browsers display errors about untrusted SSL certificates because they do not [support the Server Name Indication (SNI) protocol ↗](https://en.wikipedia.org/wiki/Server%5FName%5FIndication#Support) used by Cloudflare Universal SSL certificates.

To solve, [determine if the browser supports SNI ↗](https://caniuse.com/#feat=sni). If not, upgrade your browser.

Note

It is possible for [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) to enable non-SNI support for paid plans using any certificate.

---

## Only some of your subdomains return SSL errors

### Symptom

[Cloudflare Universal SSL certificates](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl) only cover the apex domain (`example.com`) and one level of subdomains (`blog.example.com`). If visitors to your domain observe errors accessing a second level of subdomains in their browser (such as `dev.www.example.com`) but not the first level of subdomains, resolve the issue using one of the following methods below.

### Resolution

* Purchase an [advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager) that covers `dev.www.example.com`.
* Upload a [Custom SSL certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates) that covers `dev.www.example.com`.
* Enable [Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls).
* If you have a valid certificate for the second level subdomains at your origin web server, change the DNS record for `dev.www` to [DNS Only (grey cloud)](https://developers.cloudflare.com/dns/proxy-status/).

---

## Your Cloudflare Universal SSL certificate is not active

### Symptom

All active Cloudflare domains are provided a [Universal SSL certificate](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl). If you observe SSL errors and do not have a certificate of **Type** _Universal_ within the **Edge Certificates** tab of the Cloudflare **SSL/TLS** app for your domain, the Universal SSL certificate has not yet provisioned.

Our SSL vendors verify each SSL certificate request before Cloudflare can issue a certificate for a domain name. This process may take anywhere from 15 minutes to 24 hours. Our SSL certificate vendors sometimes flag a domain name for additional review.

### Resolution

#### No Universal certificate

If your Cloudflare SSL certificate is not issued within 24 hours of Cloudflare domain activation:

* If your origin web server has a valid SSL certificate, [temporarily pause Cloudflare](https://developers.cloudflare.com/fundamentals/manage-domains/pause-cloudflare/), and
* [Contact Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) and provide a screenshot of the errors.

Temporarily pausing Cloudflare will allow the HTTPS traffic to be served properly from your origin web server while the support team investigates the issue.

#### Full DNS setup

If your domain is on a [full setup](https://developers.cloudflare.com/dns/zone-setups/full-setup/), review your DNS records.

Cloudflare SSL/TLS certificates only apply for traffic [proxied through Cloudflare](https://developers.cloudflare.com/dns/proxy-status/). If SSL errors only occur for hostnames not proxied to Cloudflare, proxy those hostnames through Cloudflare.

#### Partial DNS setup

If your domain is on a [CNAME setup (partial)](https://developers.cloudflare.com/dns/zone-setups/partial-setup/), confirm whether you have CAA DNS records enabled at your current hosting provider. If so, ensure you [specify the Certificate Authorities that Cloudflare uses](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/) to provision certificates for your domain.

---

## OCSP response error

### Symptom

Visitors to your site observe an OCSP response error.

### Resolution

This error is either caused by the browser version or an issue requiring attention by one of Cloudflare’s SSL vendors. In order to properly diagnose, [contact Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) with the following information provided by the visitor that observes the browser error:

1. The output from [https://aboutmybrowser.com/ ↗](https://aboutmybrowser.com/) .
2. The output of `https://<YOUR_DOMAIN>/cdn-cgi/trace` from the visitor’s browser.

---

## Incorrect HSTS headers

### Symptom

The HSTS headers (`Strict-Transport-Security` and `X-Content-Type-Options`) in the response do not match the configuration settings defined in your [HSTS settings](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/http-strict-transport-security/).

### Resolution

You may have configured [Response Header Transform Rules](https://developers.cloudflare.com/rules/transform/response-header-modification) that are overriding the HSTS header values defined in the **SSL/TLS** app.

1. In the Cloudflare dashboard, go to the Rules **Overview** page.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/rules/overview)
2. Under **Response Header Transform Rules**, search for a rule setting the value of one of the HSTS headers (`Strict-Transport-Security` or `X-Content-Type-Options`).
3. Delete (or edit) the rule so that the HSTS configuration settings defined in the **SSL/TLS** app are applied.
4. Repeat this procedure for the other HSTS header.

---

## Other errors

### Symptom

You are getting the error `NET::ERR_CERT_COMMON_NAME_INVALID` in your browser.

### Resolution

* Make sure that you are using a browser that supports [SNI (Server Name Indication) ↗](https://www.cloudflare.com/learning/ssl/what-is-sni/). Refer to [Browser compatibility](https://developers.cloudflare.com/ssl/reference/browser-compatibility/) for more details.
* Ensure that the hostname you are accessing is set to [proxied (orange cloud)](https://developers.cloudflare.com/dns/proxy-status/) in the DNS tab of your Cloudflare Dashboard.
* If the hostname you are accessing is a second level subdomain (such as `dev.www.example.com`), you'll need to either:  
   * Purchase an [advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager) that covers `dev.www.example.com`.  
   * Upload a [Custom SSL certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates) that covers `dev.www.example.com`.  
   * Enable [Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls)

Note

The following [openssl ↗](https://www.openssl.org/) command might help troubleshooting TLS handshake between the client and the Cloudflare network edge:

Terminal window

```

openssl s_client -connect example.com:443 -servername example.com version


```

---

## Kaspersky Antivirus

To avoid SSL errors with the Cloudflare dashboard when using Kaspersky Antivirus, allow `dash.cloudflare.com` in Kaspersky.

---

## Certificate Approval renewal email

### Symptom

When clicking `Approve Certificate` on a Certificate Approval renewal email, you get the following error message:

`An error occurred while attempting to validate your domain. Please try again later or contact support for assistance.`

### Resolution

Check the status of the certificate on the [Cloudflare dashboard ↗](https://dash.cloudflare.com?to=/:account/:zone/ssl-tls). If the status is `Active`, you can disregard this email and the error message.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/troubleshooting/general-ssl-errors/","name":"General SSL errors"}}]}
```

---

---
title: Mixed content errors
description: Fix mixed content errors caused by HTTP resources on HTTPS pages.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Mixed content errors

Domains added to Cloudflare receive SSL certificates and can serve traffic over HTTPS. However, after starting to use Cloudflare, some customers notice missing content or page rendering issues when they first serve HTTPS traffic.

Typically, the problem is due to a request for HTTP resources from a web page served over HTTPS. For example, you type `https://example.com` in a browser and the page contains an image reference via HTTP in the HTML to `<img src="http://example.com/resource.jpg">`.

Normally, if your website loads all resources securely over HTTPS, visitors observe a lock icon in the address bar of their browser.

This indicates your site has a working SSL certificate and all resources loaded by the site are loaded over HTTPS. The green lock assures visitors that their connection is safe. One of the [symptoms of mixed content](#symptoms-of-mixed-content-occurrence) is that different icons appear instead of the green lock icon.

---

## Symptoms of mixed content occurrence

Most modern browsers block HTTP requests on secure HTTPS pages. Blocked content can include images, JavaScript, CSS, or other content that affects how the page looks or behaves.

### Browser indications

Each web browser uses different methods to warn visitors about mixed content on a website, potentially including:

* A yellow triangle or information symbol beside the URL bar
* Messages mentioning "secure content"

### **Console logs**

For mixed content warnings, the web browser loads the resources but users do not see the lock icon in the URL. Warning messages appear within the browser’s debug tools:

![Screenshot of mixed content warnings displayed in a browser console.](https://developers.cloudflare.com/_astro/hc-import-mixed_content_warning.WfgcvXqC_Z29obV7.webp) 

For mixed content errors, the browser refuses to load the resources over an insecure connection:

![Screenshot of mixed content errors displayed in a browser console.](https://developers.cloudflare.com/_astro/hc-import-mixed_content_error.C3G5mm9r_129MlR.webp) 

Information on using the browser’s debug tools to locate these issues are found in the documentation for [Chrome ↗](https://developers.google.com/web/fundamentals/security/prevent-mixed-content/fixing-mixed-content) and [Firefox ↗](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed%5Fcontent). Alternatively, you can view your page source and find specific references of _http://_ for paths to other resources.

---

## Resolution

### General advice

There are two methods to resolve mixed content errors.

1. Load all resources via your HTML source without specifying the HTTP or HTTPS protocols. For example, using `/domain.com/path/to.file` instead of `http://domain.com/path/to.file`.
2. Depending on your Content Management System, check for plugins that automatically rewrite HTTP resources to HTTPS. Cloudflare provides such a service via [Automatic HTTPS Rewrites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/automatic-https-rewrites).

### WordPress users

Cloudflare recommends WordPress users to install the [Cloudflare WordPress plugin ↗](https://wordpress.org/plugins/cloudflare/) and enable the _Automatic HTTPS rewrites_ option within the plugin.

---

## Related resources

* [Debugging mixed content in Chrome ↗](https://developers.google.com/web/fundamentals/security/prevent-mixed-content/fixing-mixed-content)
* [Debugging mixed content in Firefox ↗](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed%5Fcontent)
* [Community Tip - Fixing mixed content errors ↗](https://community.cloudflare.com/t/community-tip-fixing-mixed-content-errors/42476)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/troubleshooting/mixed-content-errors/","name":"Mixed content errors"}}]}
```

---

---
title: ERR_TOO_MANY_REDIRECTS
description: Learn how to troubleshoot ERR_TOO_MANY_REDIRECTS when using Cloudflare SSL/TLS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# ERR\_TOO\_MANY\_REDIRECTS

After you [add a new domain](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) to Cloudflare, your visitors' browsers might display `ERR_TOO_MANY_REDIRECTS` or `The page isn’t redirecting properly` errors.

This error occurs when visitors get stuck in a redirect loop.

flowchart LR
accTitle: Redirect loops illustration
A[Request for <code>http://</code><code>example.com</code>] --> B[Redirect to <code>https://</code><code>example.com</code>]
B --> C[Redirect to <code>http://</code><code>example.com</code>]
C --> B
subgraph Redirect Loop
B
C
end

  
This error is commonly caused by:

* A misconfiguration of your [SSL/TLS Encryption mode](#encryption-mode-misconfigurations).
* Various settings on the [**Edge Certificates**](#edge-certificate-settings) page.
* A misconfigured [redirect rule](#redirect-rules).

Note

For assistance determining if your origin web server is responding with redirects, contact your hosting provider or site administrator.

---

## Encryption mode misconfigurations

Your domain's [SSL/TLS Encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/) controls how Cloudflare connects to your origin server and how SSL certificates presented by your origin will be validated.

This setting can cause redirect loops when the value you set in Cloudflare conflicts with the settings at your origin web server.

### Flexible encryption mode

If your domain's encryption mode is set to [**Flexible**](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/flexible/), Cloudflare sends unencrypted requests to your origin server over HTTP.

Redirect loops will occur if your origin server automatically redirects all HTTP requests to HTTPS.

flowchart TD
accTitle: Redirect loops illustration for Flexible mode
A[Request for <code>https://</code><code>example.com</code>] --> B[Encryption mode redirects to <code>http://</code><code>example.com</code>]
B --> C[Origin server redirects to <code>https://</code><code>example.com</code>]
C --> B
subgraph Cloudflare
B
end
subgraph Origin server
C
end

  
To solve this issue, either remove HTTPS redirects from your origin server or update your SSL/TLS Encryption Mode to be [**Full**](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full/) or higher (requires an SSL certificate configured at your origin server).

### Full or Full (strict) encryption mode

If your domain's encryption mode is set to [**Full**](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full/) or [**Full (strict)**](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/), Cloudflare sends encrypted requests to your origin server over HTTPS.

Redirect loops will occur if your origin server automatically redirects all HTTPS requests to HTTP.

flowchart TD
accTitle: Redirect loops illustration for Full or Full (strict) mode
A[Request for <code>http://</code><code>example.com</code>] --> B[Encryption mode redirects to <code>https://</code><code>example.com</code>]
B --> C[Origin server redirects to <code>http://</code><code>example.com</code>]
C --> B
subgraph Cloudflare
B
end
subgraph Origin server
C
end

  
To solve this issue, remove HTTP redirects from your origin server.

---

## Edge certificate settings

### Always use HTTPS

If you have [**Always Use HTTPS**](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/) enabled for your domain, Cloudflare redirects all `http` requests to `https` for all subdomains and hosts in your application.

Redirect loops will occur if your origin server automatically redirects all HTTPS requests to HTTP.

flowchart TD
accTitle: Redirect loops illustration for Always Use HTTPS
A[Request for <code>http://</code><code>example.com</code>] --> B[Always Use HTTPS redirects to <code>https://</code><code>example.com</code>]
B --> C[Origin server redirects to <code>http://</code><code>example.com</code>]
C --> B
subgraph Cloudflare
B
end
subgraph Origin server
C
end

  
To solve this issue, remove HTTPS redirects from your origin server or [disable **Always Use HTTPS**](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/).

### HSTS

If you have [**HTTP Strict Transport Security (HSTS)**](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/http-strict-transport-security/) enabled for your domain, Cloudflare directs compliant web browsers to transform `http` links to `https` links.

Redirect loops will occur if your origin server automatically redirects all HTTPS requests to HTTP or if you have your domain's encryption mode set to [**Off**](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/off/).

flowchart TD
accTitle: Redirect loops illustration for HTTP Strict Transport Security
A[Request for <code>https://</code><code>example.com</code>] --> B[Encryption mode redirects to <code>http://</code><code>example.com</code>]
B --> C[HSTS redirects to <code>https://</code><code>example.com</code>]
C --> B
C --> D[Origin server redirects to <code>http://</code><code>example.com</code>]
D --> C
subgraph Cloudflare
B
C
end
subgraph Origin server
D
end

  
To solve this issue, remove HTTPS redirects from your origin server and make sure your domain's encryption mode is [**Flexible**](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/flexible/) or higher.

Alternatively, [disable **HTTP Strict Transport Security (HSTS)**](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/http-strict-transport-security/).

---

## Redirect rules

Redirect loops can also occur if you have conflicting URL redirects.

flowchart TD
accTitle: Redirect loops illustration for redirect rules
A[Request for <code>https://</code><code>a.example.com</code>] --> B[Redirect to <code>http://</code><code>b.example.com</code>]
B --> C[Redirect to <code>https://</code><code>a.example.com</code>]
C --> B
subgraph Cloudflare
B
C
end

  
To solve this issue, review your various [redirect rules](https://developers.cloudflare.com/rules/url-forwarding/) and [Page Rules](https://developers.cloudflare.com/rules/page-rules/) to make sure no rules are not in conflict with each other.

Note

To reduce the potential for redirect loops and [mixed content errors](https://developers.cloudflare.com/ssl/troubleshooting/mixed-content-errors/), Cloudflare recommends WordPress users to install the [Cloudflare WordPress plugin ↗](https://wordpress.org/plugins/cloudflare/) at their origin web server and enable the _Automatic HTTPS rewrites_ option within the plugin.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/troubleshooting/too-many-redirects/","name":"ERR_TOO_MANY_REDIRECTS"}}]}
```

---

---
title: ERR_SSL_VERSION_OR_CIPHER_MISMATCH
description: Learn how to troubleshoot ERR_SSL_VERSION_OR_CIPHER_MISMATCH when using Cloudflare SSL/TLS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# ERR\_SSL\_VERSION\_OR\_CIPHER\_MISMATCH

After you [add a new domain](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) to Cloudflare, your visitors' browsers might display one of the following errors:

* `ERR_SSL_VERSION_OR_CIPHER_MISMATCH` (Chrome)
* `Unsupported protocol The client and server don’t support a common SSL protocol version or cipher suite` (Chrome)
* `SSL_ERROR_NO_CYPHER_OVERLAP` (Firefox)

This error occurs when your domain or subdomain is not covered by an SSL/TLS certificate, which is usually caused by:

* A [delay in certificate activation](#certificate-activation).
* An [unproxied domain or subdomain DNS record](#proxied-dns-records).
* An [expired Custom certificate](#certificate-expiration).
* A [multi-level subdomain](#multi-level-subdomains) (`test.dev.example.com`).

## Decision tree

flowchart TD
accTitle: Troubleshooting ERR_SSL_VERSION_OR_CIPHER_MISMATCH decision tree
A>Is your certificate active?] -- Yes --> B>Is the DNS record proxied?]
A -- No --> C[Wait for certificate to activate or pause Cloudflare]
B -- No --> D[Proxy the DNS record]
B -- Yes --> E>Are you using a custom certificate?]
E -- Yes --> F[Custom certificate may be expired]
E -- No --> G>Are you accessing a multi-level subdomain?]
G -- Yes --> H[Get an advanced or custom certificate]

---

## Certificate activation

For domains on a [primary setup (full)](https://developers.cloudflare.com/dns/zone-setups/full-setup/)[1](#user-content-fn-1), your domain should **automatically** receive its Universal SSL certificate within **15 minutes to 24 hours** of domain activation[2](#user-content-fn-2).

This certificate will cover your zone apex (`example.com`) and all first-level subdomains (`subdomain.example.com`), and is provisioned even if your records are DNS only. However, the certificate will only be presented if your domain or subdomains are [proxied](https://developers.cloudflare.com/dns/proxy-status/).

## Footnotes

1. The most common Cloudflare setup that involves changing your authoritative nameservers. [↩](#user-content-fnref-1)
2. Provisioning time depends on certain security checks and other requirements mandated by Certificate Authorities (CA). [↩](#user-content-fnref-2)

### Potential issues

If your visitors experience `ERR_SSL_VERSION_OR_CIPHER_MISMATCH` (Chrome) or `SSL_ERROR_NO_CYPHER_OVERLAP` (Firefox), check the status of your Universal certificate:

1. Log into the [Cloudflare dashboard ↗](https://dash.cloudflare.com).
2. Choose your account and domain.
3. Go to the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page.
4. Find the certificate with the **Type** of **Universal**.
5. Make sure the **Status** is **Active**.

If the **Status** is anything other than **Active**, you can either wait a bit longer for certificate activation or take immediate action.

### Solutions

If you need to immediately resolve this error, [temporarily pause Cloudflare](https://developers.cloudflare.com/fundamentals/manage-domains/pause-cloudflare/).

Since Universal certificates can take up to 24 hours to be issued, wait and [monitor the certificate's status](https://developers.cloudflare.com/ssl/reference/certificate-statuses/#ssltls). Once your certificate becomes **Active**, unpause Cloudflare using whichever method you used previously.

If your certificate is still not **Active** after 24 hours, try the various troubleshooting steps used to [resolve timeout issues](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/troubleshooting/#resolve-a-timed-out-state). If these methods are successful (and your certificate becomes **Active**), unpause Cloudflare using whichever method you used previously.

---

## Proxied DNS records

Cloudflare Universal and Advanced certificates only cover the domains and subdomains you have [proxied through Cloudflare](https://developers.cloudflare.com/dns/proxy-status/).

If the **Proxy status** of `A`, `AAAA`, or `CNAME` records for a hostname are **DNS-only**, you will need to change it to **Proxied**.

![Proxy status affects how Cloudflare treats traffic intended for specific DNS records](https://developers.cloudflare.com/_astro/proxy-status-screenshot.uxgurbGi_2igVHO.webp) 

---

## Certificate expiration

If you have a [Custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) and visitors experience `ERR_SSL_VERSION_OR_CIPHER_MISMATCH` (Chrome) or `SSL_ERROR_NO_CYPHER_OVERLAP` (Firefox), [check its status](https://developers.cloudflare.com/ssl/reference/certificate-statuses/#ssltls) to make sure it is not expired.

If it is expired, [upload a replacement certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/renewing/).

---

## Multi-level subdomains

By default, Cloudflare [Universal SSL certificates](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) only cover your apex domain and one level of subdomain.

| Hostname                 | Covered by Universal certificate? |
| ------------------------ | --------------------------------- |
| example.com              | Yes                               |
| www.example.com          | Yes                               |
| docs.example.com         | Yes                               |
| dev.docs.example.com     | No                                |
| test.dev.api.example.com | No                                |

This means that you might experience `ERR_SSL_VERSION_OR_CIPHER_MISMATCH` (Chrome) or `SSL_ERROR_NO_CYPHER_OVERLAP` (Firefox) on multi-level subdomains.

To prevent insecure connections on a multi-level subdomain, do one of the following:

* Enable [Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/), which automatically issues individual certificates to your proxied hostnames not covered by a Universal certificate.
* Order an [Advanced Certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/) covering the subdomain.
* Upload a [Custom Certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) covering the subdomain.

If none of these solutions work, you could also remove the multi-level subdomain.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/troubleshooting/version-cipher-mismatch/","name":"ERR_SSL_VERSION_OR_CIPHER_MISMATCH"}}]}
```

---

---
title: SSL/TLS FAQ
description: Get answers to commonly asked questions about the certificates you can obtain through Cloudflare and the CAs that Cloudflare partners with.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# SSL/TLS FAQ

Refer to this page for frequently asked questions about Cloudflare SSL/TLS certificate offerings and the CAs that Cloudflare partners with.

---

## General

### Does Cloudflare issue both RSA and ECDSA certificates?

Yes. Cloudflare can issue both RSA and ECDSA certificates.

### Are Cloudflare SSL certificates shared?

No. Cloudflare SSL/TLS certificates are not shared across domains nor across customers.

### If I have multiple Cloudflare certificates, which one is used?

Cloudflare certificates are prioritized by a combination of hostname specificity, zone specificity, and certificate type. For more details, refer to [Certificate and hostname priority](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/).

### Why do I see a Cloudflare certificate when an SSL certificate is installed at my website?

Cloudflare must decrypt traffic in order to cache and filter malicious traffic. Cloudflare either re-encrypts traffic or sends plain text traffic to the origin web server depending on your domain's [encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/).

---

## Certificate authorities (CAs)

### Which certificate authorities does Cloudflare use?

Cloudflare uses Let's Encrypt, Google Trust Services, SSL.com, and Sectigo. You can see a complete list of products and available CAs and algorithms in the [certificate authorities reference page](https://developers.cloudflare.com/ssl/reference/certificate-authorities/).

Sectigo is only used for [backup certificates](https://developers.cloudflare.com/ssl/edge-certificates/backup-certificates/).

### Are there any CA limitations I should know about?

Refer to the [certificate authorities reference page](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) for a list of limitations for every CA in our pipeline. There you can also find information about device and browser compatibility.

### I do not want to use the CAs that Cloudflare partners with. What can I do?

If you are on a Business or Enterprise plan, you can [upload a certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/#upload-a-custom-certificate) from the CA of your choice.

### I am missing the CAs that Cloudflare uses in my trust store. What should I do?

You can use [CFSSL trust store ↗](https://github.com/cloudflare/cfssl%5Ftrust), which includes all of the CAs that are used by Cloudflare managed certificates.

---

## CAA records

### What is CAA and how can I create one?

A Certificate Authority Authorization (CAA) DNS record specifies which certificate authorities (CAs) are allowed to issue certificates for a domain. This record reduces the chance of unauthorized certificate issuance and promotes standardization across your organization.

  
For more details, refer to [Add CAA records](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/).

### How does Cloudflare evaluate CAA records?

CAA records are evaluated by a CA, not by Cloudflare. For details, refer to [RFC 8659 ↗](https://www.rfc-editor.org/rfc/rfc8659.html#name-relevant-resource-record-se).

Setting a CAA record to specify one or more particular CAs does not affect which CA Cloudflare uses to issue universal or advanced certificates for your domain. If you wish, you can specify CAs associated with Cloudflare certificates when [ordering an advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/).

### What are the dangers of setting CAA records?

If you are part of a large organization or one where multiple parties are tasked with obtaining SSL certificates, [include CAA records](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/) that allow issuance for all CAs applicable for your organization. Failure to do so can inadvertently block SSL issuance for other parts of your organization.

### What CAA records do I need to allow issuance from Cloudflare CAs?

You can find CAA records associated with every Cloudflare CA in the [certificate authorities reference page](https://developers.cloudflare.com/ssl/reference/certificate-authorities/#caa-records). If you are using Cloudflare as your DNS provider, then the CAA records will be added on your behalf.

---

## Universal SSL

### I am using Universal SSL and I would like to use a different CA. How can I do that?

To be able to specify a CA, you must purchase [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/). Through Advanced Certificate Manager, you can choose the certificate authority when ordering an advanced certificate or you can choose a default CA when using [Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/).

If you are on a Business or Enterprise plan, you can [upload a certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/#upload-a-custom-certificate) from the CA of your choice. In this case, certificate issuance and renewal will have to be managed by you.

### Does Cloudflare issue both RSA and ECDSA certificates for Universal certificates?

Universal certificates on free zones only receive an ECDSA certificate. Paid zones receive an RSA and ECDSA certificate.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/faq/","name":"SSL/TLS FAQ"}}]}
```

---

---
title: Changelog
description: Track the latest updates and changes to Cloudflare SSL/TLS features.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Changelog

[ Subscribe to RSS ](https://developers.cloudflare.com/changelog/rss/ssl.xml) 

## 2026-04-07

  
**Manage mTLS and BYO CA certificates from the Cloudflare dashboard**   

You can now manage mutual TLS (mTLS) and Bring Your Own Certificate Authority (BYO CA) configurations directly from the Cloudflare dashboard — no API required.

Previously, these advanced workflows required the Cloudflare API. The following are now available in the dashboard:

* **AOP certificate management** — Upload and manage your own certificate authorities for [Authenticated Origin Pulls (AOP)](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/)directly from the dashboard.
* **BYO Client mTLS certificate management** — Upload and manage your own CA certificates for [client mTLS enforcement](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/)without needing API access.
* **CDN hostname to client mTLS certificate mapping** — Associate client mTLS certificates with specific hostnames directly from the dashboard.

## 2025-08-25

  
**Manage and deploy your AI provider keys through Bring Your Own Key (BYOK) with AI Gateway, now powered by Cloudflare Secrets Store**   

Cloudflare Secrets Store is now integrated with AI Gateway, allowing you to store, manage, and deploy your AI provider keys in a secure and seamless configuration through [Bring Your Own Key ↗](https://developers.cloudflare.com/ai-gateway/configuration/bring-your-own-keys/). Instead of passing your AI provider keys directly in every request header, you can centrally manage each key with Secrets Store and deploy in your gateway configuration using only a reference, rather than passing the value in plain text.

You can now create a secret directly from your AI Gateway [in the dashboard ↗](http://dash.cloudflare.com/?to=/:account/ai-gateway) by navigating into your gateway -> **Provider Keys** \-> **Add**.

![Import repo or choose template](https://developers.cloudflare.com/_astro/add-secret-ai-gateway.B-SIPr6s_jJjDD.webp) 

You can also create your secret with the newly available **ai\_gateway** scope via [wrangler ↗](https://developers.cloudflare.com/workers/wrangler/commands/), the [Secrets Store dashboard ↗](http://dash.cloudflare.com/?to=/:account/secrets-store), or the [API ↗](https://developers.cloudflare.com/api/resources/secrets%5Fstore/).

Then, pass the key in the request header using its Secrets Store reference:

Terminal window

```

curl -X POST https://gateway.ai.cloudflare.com/v1/<ACCOUNT_ID>/my-gateway/anthropic/v1/messages \

 --header 'cf-aig-authorization: ANTHROPIC_KEY_1 \

 --header 'anthropic-version: 2023-06-01' \

 --header 'Content-Type: application/json' \

 --data  '{"model": "claude-3-opus-20240229", "messages": [{"role": "user", "content": "What is Cloudflare?"}]}'


```

Or, using Javascript:

```

import Anthropic from '@anthropic-ai/sdk';


const anthropic = new Anthropic({

 apiKey: "ANTHROPIC_KEY_1",

 baseURL: "https://gateway.ai.cloudflare.com/v1/<ACCOUNT_ID>/my-gateway/anthropic",

});


const message = await anthropic.messages.create({

 model: 'claude-3-opus-20240229',

 messages: [{role: "user", content: "What is Cloudflare?"}],

 max_tokens: 1024

});


```

For more information, check out the [blog ↗](https://blog.cloudflare.com/ai-gateway-aug-2025-refresh)!

## 2025-05-27

  
**Increased limits for Cloudflare for SaaS and Secrets Store free and Pay-as-you-go plans**   

With upgraded limits to [all free and paid plans ↗](https://www.cloudflare.com/plans/), you can now scale more easily with [Cloudflare for SaaS ↗](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) and [Secrets Store ↗](https://developers.cloudflare.com/secrets-store/).

[Cloudflare for SaaS ↗](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) allows you to extend the benefits of Cloudflare to your customers via their own custom or vanity domains. Now, the [limit for custom hostnames ↗](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/plans/) on a Cloudflare for SaaS Pay-as-you-go plan has been **raised from 5,000 custom hostnames to 50,000 custom hostnames.**

With custom origin server -- previously an enterprise-only feature -- you can route traffic from one or more custom hostnames somewhere other than your default proxy fallback. [Custom origin server ↗](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/) is now available to Cloudflare for SaaS customers on Free, Pro, and Business plans.

You can enable custom origin server on a per-custom hostname basis [via the API ↗](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) or the UI:

![Import repo or choose template](https://developers.cloudflare.com/_astro/custom-origin-server.B-BXcG-1_ZUd9i6.webp) 

Currently [in beta with a Workers integration ↗](https://blog.cloudflare.com/secrets-store-beta/), [Cloudflare Secrets Store ↗](https://developers.cloudflare.com/secrets-store/) allows you to store, manage, and deploy account level secrets from a secure, centralized platform your [Cloudflare Workers ↗](https://developers.cloudflare.com/workers/). Now, you can create and deploy **100 secrets per account**. Try it out [in the dashboard ↗](http://dash.cloudflare.com/?to=/:account/secrets-store), with [Wrangler ↗](https://developers.cloudflare.com/secrets-store/integrations/workers/), or [via the API ↗](https://developers.cloudflare.com/api/resources/secrets%5Fstore/) today.

## 2025-04-09

  
**Cloudflare Secrets Store now available in Beta**   

Cloudflare Secrets Store is available today in Beta. You can now store, manage, and deploy account level secrets from a secure, centralized platform to your Workers.

![Import repo or choose template](https://developers.cloudflare.com/_astro/secrets-store-landing-page.BQoEWsq8_ZUrGq1.webp) 

To spin up your Cloudflare Secrets Store, simply click the new Secrets Store tab [in the dashboard ↗](http://dash.cloudflare.com/?to=/:account/secrets-store) or use this Wrangler command:

Terminal window

```

wrangler secrets-store store create <name> --remote


```

The following are supported in the Secrets Store beta:

* Secrets Store UI & API: create your store & create, duplicate, update, scope, and delete a secret
* Workers UI: bind a new or existing account level secret to a Worker and deploy in code
* Wrangler: create your store & create, duplicate, update, scope, and delete a secret
* Account Management UI & API: assign Secrets Store permissions roles & view audit logs for actions taken in Secrets Store core platform

For instructions on how to get started, visit our [developer documentation](https://developers.cloudflare.com/secrets-store/).

## 2025-02-14

  
**Upload a certificate bundle with an RSA and ECDSA certificate per custom hostname**   

Cloudflare has supported both RSA and ECDSA certificates across our platform for a number of years. Both certificates offer the same security, but ECDSA is more performant due to a smaller key size. However, RSA is more widely adopted and ensures compatibility with legacy clients. Instead of choosing between them, you may want both – that way, ECDSA is used when clients support it, but RSA is available if not.

Now, you can upload both an RSA and ECDSA certificate on a custom hostname via the API.

```

curl -X POST https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames \

    -H 'Content-Type: application/json' \

    -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \

    -H "X-Auth-Key: $CLOUDFLARE_API_KEY" \

    -d '{

    "hostname": "hostname",

    "ssl": {

        "custom_cert_bundle": [

            {

                "custom_certificate": "RSA Cert",

                "custom_key": "RSA Key"

            },

            {

                "custom_certificate": "ECDSA Cert",

                "custom_key": "ECDSA Key"

            }

        ],

        "bundle_method": "force",

        "wildcard": false,

        "settings": {

            "min_tls_version": "1.0"

        }

    }

}’


```

You can also:

* [Upload](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/) an RSA or ECDSA certificate to a custom hostname with an existing ECDSA or RSA certificate, respectively.
* [Replace](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/subresources/certificate%5Fpack/subresources/certificates/methods/update/) the RSA or ECDSA certificate with a certificate of its same type.
* [Delete](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/subresources/certificate%5Fpack/subresources/certificates/methods/delete/) the RSA or ECDSA certificate (if the custom hostname has both an RSA and ECDSA uploaded).

This feature is available for Business and Enterprise customers who have purchased custom certificates.

## 2024-10-18

**New cloudflare\_branding flag allows hostnames with over 64 characters for all CAs**

To order certificates for hostnames longer than 64 characters, customers can now use the `cloudflare_branding` flag when ordering a certificate via [API ↗](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/create/). Setting `cloudflare_branding` to `true` will cause `sni.cloudflaressl.com` to be used as the common name, while the long hostname is added as part of the subject alternative name (SAN).

## 2024-09-19

**SSL.com available with ACM and SSL for SaaS**

SSL.com is one of the [certificate authorities](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) that Cloudflare partners with. SSL.com is now available as an option to customers with Advanced Certificate Manager (ACM) or SSL for SaaS. Consider our [reference documentation](https://developers.cloudflare.com/ssl/reference/certificate-authorities/#sslcom) for details.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/changelog/","name":"Changelog"}}]}
```

---

---
title: Authenticated Origin Pulls (mTLS)
description: Authenticated Origin Pulls helps ensure requests to your origin server come from the Cloudflare network.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Authenticated Origin Pulls (mTLS)

Authenticated Origin Pulls (AOP) helps ensure requests to your origin server come from the Cloudflare network, which provides an additional layer of security on top of [Full](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full/) or [Full (strict)](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/) encryption modes.

Check your encryption mode

Authenticated Origin Pulls does not apply when your [SSL/TLS encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/) is set to **Off** or **Flexible**.

Without AOP, anyone who discovers your origin server's IP address can send requests directly, bypassing Cloudflare and all its protections. When you combine AOP with the [Cloudflare Web Application Firewall (WAF)](https://developers.cloudflare.com/waf/), your origin only accepts requests that have passed through Cloudflare, which means every request is evaluated by the WAF before reaching your server.

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

## Configuration levels

AOP has three independent configuration levels. Each uses its own certificate and enablement setting, and each requires configuration on your origin server. Refer to the specific setup guides for details.

* [Global](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/global/): Uses a Cloudflare-provided certificate that is shared across all Cloudflare accounts. Applies to all proxied traffic on the zone. This is the simplest setup but only guarantees that a request is coming from the Cloudflare network.
* [Zone-level](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/zone-level/): Uses a certificate that you upload. Applies to all proxied traffic on the zone. Provides stricter security because the certificate is exclusive to your account. Zone-level certificates take precedence over global certificates.
* [Per-hostname](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/): Uses a certificate that you upload, applied to specific hostnames. Per-hostname certificates take precedence over zone-level and global certificates for the specified hostname.

Note

[Global AOP](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/global/), [zone-level AOP](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/zone-level/), and [per-hostname AOP](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/) are three independent configurations. Enabling or disabling one does not affect the others.

## When to use your own certificate

Global AOP uses a Cloudflare-provided certificate shared across all accounts, so it only proves a request came from the Cloudflare network — not from your account specifically. If you need to guarantee requests come from your account, set up [zone-level](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/zone-level/) or [per-hostname](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/) AOP with your own certificate.

Using your own certificate is also required for [FIPS ↗](https://en.wikipedia.org/wiki/Federal%5FInformation%5FProcessing%5FStandards) compliance. For broader origin protection guidance, refer to [Protect your origin server](https://developers.cloudflare.com/fundamentals/security/protect-your-origin-server/).

## Related topics

* [SSL/TLS Encryption Modes](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/)
* [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/","name":"Authenticated Origin Pulls (mTLS)"}}]}
```

---

---
title: AWS integration
description: Learn how to set up Cloudflare Authenticated Origin Pulls with the AWS Application Load Balancer.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# AWS integration

This guide will walk you through how to set up [per-hostname](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/) authenticated origin pulls to securely connect to an AWS Application Load Balancer using [mutual TLS verify ↗](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/mutual-authentication.html).

## Before you begin

* You should already have your AWS account and [EC2 ↗](https://docs.aws.amazon.com/ec2/?icmpid=docs%5Fhomepage%5Ffeaturedsvcs) configured.
* Note that this tutorial uses command-line interface (CLI) to generate a custom certificate, and [API calls](https://developers.cloudflare.com/fundamentals/api/get-started/) to configure Cloudflare Authenticated Origin Pulls.
* For the most up-to-date documentation on how to set up AWS, refer to the [AWS documentation ↗](https://docs.aws.amazon.com/).

## 1\. Generate a custom certificate

1. Run the following command to generate a 4096-bit RSA private key, using AES-256 encryption. Enter a passphrase when prompted.

Terminal window

```

openssl genrsa -aes256 -out rootca.key 4096


```

1. Create the CA root certificate. When prompted, fill in the information to be included in the certificate. For the `Common Name` field, use the domain name as value, not the hostname.

Terminal window

```

openssl req -x509 -new -nodes -key rootca.key -sha256 -days 1826 -out rootca.crt


```

1. Create a Certificate Signing Request (CSR). When prompted, fill in the information to be included in the request. For the `Common Name` field, use the hostname as value.

Terminal window

```

openssl req -new -nodes -out cert.csr -newkey rsa:4096 -keyout cert.key


```

1. Sign the certificate using the `rootca.key` and `rootca.crt` created in previous steps.

Terminal window

```

openssl x509 -req -in cert.csr -CA rootca.crt -CAkey rootca.key -CAcreateserial -out cert.crt -days 730 -sha256 -extfile ./cert.v3.ext


```

1. Make sure the certificate extensions file `cert.v3.ext` specifies the following:

```

basicConstraints=CA:FALSE


```

## 2\. Configure AWS Application Load Balancer

1. Upload the `rootca.cert` to an [S3 bucket ↗](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingBucket.html).
2. [Create a trust store ↗](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/mutual-authentication.html#create-trust-store) at your EC2 console, indicating the **S3 URI** where you uploaded the certificate.
3. Create an EC2 instance and install an HTTPD daemon. Choose an [instance type ↗](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html) according to your needs - it can be a minimal instance eligible to [AWS Free Tier ↗](https://aws.amazon.com/free/). This tutorial was based on an example using t2.micro and [Amazon Linux 2023 ↗](https://docs.aws.amazon.com/linux/al2023/ug/what-is-amazon-linux.html).

Terminal window

```

sudo yum install -y httpd

sudo systemctl start httpd


```

1. Create a [target group ↗](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-application-load-balancer.html#configure-target-group) for your Application Load Balancer.  
   * Choose **Instances** as target type.  
   * Specify port `HTTP/80`.
2. After you finish configuring the target group, confirm that the target group is [healthy ↗](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-health-checks.html).
3. [Configure a load balancer and a listener ↗](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-application-load-balancer.html#configure-load-balancer).  
   * Choose the **Internet-facing** scheme.  
   * Switch the listener to port `443` so that the **mTLS** option is available, and select the target group created in previous steps.  
   * For **Default SSL/TLS server certificate**, choose **Import certificate** \> **Import to ACM**, and add the certificate private key and body.  
   * Under **Client certificate handling**, select **Verify with trust store**.
4. Save your settings.
5. (Optional) Run the following commands to confirm that the Application Load Balancing is asking for the client certificate.

Terminal window

```

openssl s_client -verify 5 -connect <your-application-load-balancer>:443 -quiet -state


```

Since you have not yet uploaded the certificate to Cloudflare, the connection should fail (`read:errno=54`, for example).

You can also run `curl --verbose` and confirm `Request CERT (13)` is present within the SSL/TLS handshake:

Terminal window

```

curl --verbose https://<your-application-load-balancer>

...

* TLSv1.2 (IN), TLS handshake, Request CERT (13):

...


```

## 3\. Configure Cloudflare

1. [Upload the certificate](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/hostname%5Fcertificates/methods/create/) you created in [Step 1](#1-generate-a-custom-certificate) to Cloudflare. You should use the leaf certificate, not the root CA.

Terminal window

```

MYCERT="$(cat cert.crt|perl -pe 's/\r?\n/\\n/'|sed -e 's/..$//')"

MYKEY="$(cat cert.key|perl -pe 's/\r?\n/\\n/'|sed -e's/..$//')"


request_body=$(< <(cat <<EOF

{

"certificate": "$MYCERT",

"private_key": "$MYKEY",

"bundle_method":"ubiquitous"

}

EOF

))


# Push the certificate


curl --silent \

"https://api.cloudflare.com/client/v4/zones/$ZONEID/origin_tls_client_auth/hostnames/certificates" \

--header "Content-Type: application/json" \

--header "X-Auth-Email: $MYAUTHEMAIL" \

--header "X-Auth-Key: $MYAUTHKEY" \

--data "$request_body"


```

1. [Associate the certificate with the hostname](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/hostnames/methods/update/) that should use it.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`

Enable or Disable a Hostname for Client Authentication

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/origin_tls_client_auth/hostnames" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "config": [

        {

            "enabled": true,

            "cert_id": "<CERT_ID>",

            "hostname": "<YOUR_HOSTNAME>"

        }

    ]

  }'


```

Note

Make sure your [encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/) is set to **Full** or higher. If you only want to adjust this setting for a specific hostname, use [Configuration Rules](https://developers.cloudflare.com/rules/configuration-rules/settings/#ssl).

---

## Roll back the Cloudflare configuration

1. Use a [PUT request](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/hostnames/methods/update/) to disable Authenticated Origin Pulls on the hostname.  
Required API token permissions  
At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:  
   * `SSL and Certificates Write`  
Enable or Disable a Hostname for Client Authentication  
```  
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/origin_tls_client_auth/hostnames" \  
  --request PUT \  
  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \  
  --json '{  
    "config": [  
        {  
            "enabled": false,  
            "cert_id": "<CERT_ID>",  
            "hostname": "<YOUR_HOSTNAME>"  
        }  
    ]  
  }'  
```
2. (Optional) Use a [GET request](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/hostname%5Fcertificates/methods/list/) to obtain a list of the client certificate IDs. You will need the ID of the certificate you want to remove for the following step.  
Required API token permissions  
At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:  
   * `SSL and Certificates Write`  
   * `SSL and Certificates Read`  
List Certificates  
```  
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/origin_tls_client_auth/hostnames/certificates" \  
  --request GET \  
  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"  
```
3. Use the [Delete hostname client certificate](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/hostname%5Fcertificates/methods/delete/) endpoint to remove the certificate you had uploaded.  
Required API token permissions  
At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:  
   * `SSL and Certificates Write`  
Delete Hostname Client Certificate  
```  
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/origin_tls_client_auth/hostnames/certificates/$CERTIFICATE_ID" \  
  --request DELETE \  
  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"  
```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/","name":"Authenticated Origin Pulls (mTLS)"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/aws-alb-integration/","name":"AWS integration"}}]}
```

---

---
title: About
description: How Authenticated Origin Pulls use mTLS to verify Cloudflare connections.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# About

## Simple explanation

When visitors request content from your domain, Cloudflare first attempts to serve content from the cache. If this attempt fails, Cloudflare sends a request — or an `origin pull` — back to your origin web server to get the content.

Authenticated Origin Pulls makes sure that all of these `origin pulls` come from Cloudflare. Put another way, Authenticated Origin Pulls ensures that any HTTPS requests outside of Cloudflare will not receive a response from your origin.

This block also applies for requests to [unproxied DNS records](https://developers.cloudflare.com/dns/proxy-status/#dns-only-records) in Cloudflare.

Warning

The Cloudflare-provided certificate used by [global AOP](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/global/) is not exclusive to your account. It only guarantees that a request is coming from the Cloudflare network.

For stricter security, set up [zone-level](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/zone-level/) or [per-hostname](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/) AOP with your own certificate and consider [other security measures for your origin](https://developers.cloudflare.com/fundamentals/security/protect-your-origin-server/).

## Detailed explanation

Cloudflare enforces authenticated origin pulls by adding an extra layer of TLS client certificate authentication when establishing a connection between Cloudflare and the origin web server.

For more details, refer to the [introductory blog post ↗](https://blog.cloudflare.com/protecting-the-origin-with-tls-authenticated-origin-pulls/).

---

### Types of handshakes

For more details, refer to [What is a TLS handshake? ↗](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/).

**Standard TLS handshake**

![Diagram showing the Standard TLS handshake](https://developers.cloudflare.com/_astro/client-auth-tls-standard.DZBqll1L_xiYbX.webp) 

**Client authenticated TLS handshake**

![Diagram showing the client authenticated TLS handshake](https://developers.cloudflare.com/_astro/client-auth-tls-handshake.B9OeA94c_Z2s8D3v.webp) 

### Comparison diagrams

Without Authenticated Origin Pulls, Cloudflare performs standard TLS handshakes between a client device and Cloudflare and Cloudflare and your origin. This is true even if you have [**Full**](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full/) or [**Full (strict)**](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/) encryption modes enabled.

    flowchart TD
      accTitle: Connection diagram without Authenticated Origin Pulls
      A[End user query for <code>example.com</code>] --Standard TLS Handshake--> B[Cloudflare network]
      B --Standard TLS Handshake--> C[Origin server]
      D[External device] --Standard TLS Handshake ----> C

  
This lack of authentication means that - even if your origin is [protected behind Cloudflare](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/) \- attackers with your origin's IP address will still receive a response from your origin for HTTPS requests.

With Authenticated Origin Pulls, Cloudflare performs standard TLS handshakes between a client device and Cloudflare, but a client-authenticated TLS handshake between Cloudflare and your origin.

    flowchart TD
      accTitle: Connection diagram with Authenticated Origin Pulls
      A[End user query for <code>example.com</code>] --Standard TLS Handshake--> B[Cloudflare network]
      B --Client authenticated TLS Handshake--> C[Origin server]
      D[External device] --Standard TLS Handshake -----x C

  
This additional layer of authentication ensures that any HTTPS requests outside of Cloudflare will not receive a response from your origin.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/","name":"Authenticated Origin Pulls (mTLS)"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/explanation/","name":"About"}}]}
```

---

---
title: Global
description: Set up global Authenticated Origin Pulls for all hostnames.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Global

When you enable global Authenticated Origin Pulls (AOP), Cloudflare uses a Cloudflare-provided client certificate for all proxied traffic to your zone. This certificate is shared across all Cloudflare accounts and guarantees that the request is coming from the Cloudflare network.

Global, [zone-level](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/zone-level/), and [per-hostname](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/) AOP are independent configurations. Enabling or disabling one does not affect the others.

## Before you begin

* Make sure your zone is using an [SSL/TLS encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/) of **Full** or higher.
* Consider your security and certificate needs:  
   * The Cloudflare-provided certificate is not exclusive to your account. It only guarantees that a request is coming from the Cloudflare network. If you need stricter security, set up [zone-level](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/zone-level/) or [per-hostname](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/) AOP with your own certificate instead.  
   * Global AOP is applied to all proxied hostnames on your zone, including [custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/) configured on a Cloudflare for SaaS zone. If you need a different AOP certificate for different custom hostnames, use [per-hostname AOP](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/).

## 1\. Download the Cloudflare certificate

[Download the Cloudflare authenticated origin pull certificate (.PEM)](https://developers.cloudflare.com/ssl/static/authenticated%5Forigin%5Fpull%5Fca.pem) and upload it to your origin server. This certificate is **not** the same as the [Cloudflare Origin CA certificate](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/).

## 2\. Configure origin to accept client certificates

With the certificate installed, set up your origin web server to accept client certificates.

Check the examples below for Apache and NGINX or refer to your origin web server documentation - for example, [HAProxy ↗](https://www.haproxy.com/documentation/hapee/latest/security/authentication/client-certificate-authentication/), [Traefik ↗](https://doc.traefik.io/traefik/https/tls/#client-authentication-mtls), [Caddy ↗](https://caddyserver.com/docs/json/apps/http/servers/tls%5Fconnection%5Fpolicies/client%5Fauthentication/mode/).

Apache example

```

SSLCACertificateFile /path/to/origin-pull-ca.pem


```

For this example, you would have saved your certificate to `/path/to/origin-pull-ca.pem`.

Rename the downloaded .PEM file and upload it to `/path/to/origin-pull-ca.pem` before applying the settings. 

NGINX example

```

ssl_verify_client optional;

ssl_client_certificate /etc/nginx/certs/cloudflare.crt;


```

For this example, you would have saved your certificate to `/etc/nginx/certs/cloudflare.crt`.

Rename the downloaded .PEM file and upload it to `/etc/nginx/certs/cloudflare.crt` before applying the settings. 

At this point, you may also want to enable logging on your origin so that you can verify the configuration is working.

## 3\. Enable global Authenticated Origin Pulls

* [ Dashboard ](#tab-panel-10491)
* [ API ](#tab-panel-10492)

1. Go to the **Origin Server** page.  
[ Go to **Origin Server** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/origin)
2. Select the **Authenticated Origin Pulls** tab.
3. In the **Global** section, switch the toggle to **On**.

To enable or disable global Authenticated Origin Pulls with the API, use the [Edit zone setting endpoint](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) with `tls_client_auth` as the setting name in the URI path, and the `value` parameter set to your desired setting (`"on"` or `"off"`).

## 4\. Enforce validation check on your origin

Once you can confirm everything is working as expected for your specific origin setup, configure your origin to enforce the authentication.

Apache example

```

SSLVerifyClient require


```

NGINX example

```

ssl_verify_client on;


```

After completing the process, you can use `curl` to send requests directly to your origin IPs, verifying that the requests fail due to certificate validation being enforced.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/","name":"Authenticated Origin Pulls (mTLS)"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/set-up/","name":"Setup"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/set-up/global/","name":"Global"}}]}
```

---

---
title: Manage certificates
description: Upload and manage certificates for Authenticated Origin Pulls.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Manage certificates

Refer to the following sections to learn how to manage certificates used with [zone-level](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/zone-level/) and [per-hostname](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/) Authenticated Origin Pulls. [Global AOP](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/global/) uses a Cloudflare-provided certificate and does not require certificate management.

---

## Expired certificates

Cloudflare does not delete client certificates upon expiration unless you send a delete request to the Cloudflare API for the relevant certificate ([Delete a zone-level certificate](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/zone%5Fcertificates/methods/delete/) or [Delete a hostname-level certificate](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/hostname%5Fcertificates/methods/delete/)). If your origin only accepts a valid client certificate, it will drop requests when the certificate expires.

Make sure you have [notifications](https://developers.cloudflare.com/notifications/notification-available/#ssltls) set up to get alerts 30 days and 14 days before an AOP certificate expires.

---

## Use specialized certificates

To apply different client certificates simultaneously at the zone and hostname level, you can combine zone-level and per-hostname custom certificates.

First, set up [zone-level AOP](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/zone-level/) using your certificate. Then, upload specialized certificates for [individual hostnames](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/). Per-hostname certificates take precedence over zone-level certificates for the specified hostname.

---

## Replace a certificate without downtime via API

No automatic removal

Cloudflare does not delete client certificates upon expiration unless you send a delete request to the Cloudflare API for the relevant certificate ([Delete a zone-level certificate](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/zone%5Fcertificates/methods/delete/) or [Delete a hostname-level certificate](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/hostname%5Fcertificates/methods/delete/)).

### Per-hostname

1. [Upload the new certificate](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/hostname%5Fcertificates/methods/create/).
2. [List your certificates](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/hostname%5Fcertificates/methods/list/) and note the ID for the certificate you uploaded.
3. [Enable Authenticated Origin Pulls for the specific hostname](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/hostnames/methods/update/), using the ID obtained in step 2 to specify the certificate you want to use:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`

Enable or Disable a Hostname for Client Authentication

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/origin_tls_client_auth/hostnames" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "config": [

        {

            "enabled": true,

            "hostname": "<HOSTNAME>",

            "cert_id": "<CERT_ID>"

        }

    ]

  }'


```

Note

If you keep both certificates, the API will state `active` for both but the most recently deployed certificate will be the one enabled and used.

### Zone-level

1. [Upload the new certificate](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/zone%5Fcertificates/methods/create/).
2. [Check whether new certificate is Active](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/zone%5Fcertificates/methods/get/).
3. Once certificate is active, [delete the previous certificate](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/zone%5Fcertificates/methods/delete/).

Note

If you keep both certificates, the API will state `active` for both but the most recently deployed certificate will be the one enabled and used.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/","name":"Authenticated Origin Pulls (mTLS)"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/set-up/","name":"Setup"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/set-up/manage-certificates/","name":"Manage certificates"}}]}
```

---

---
title: Per-hostname
description: Set up per-hostname Authenticated Origin Pulls with custom certificates.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Per-hostname

When you enable per-hostname Authenticated Origin Pulls (AOP), all proxied traffic to the specified hostname is authenticated at the origin web server using a certificate that you upload. You can use client certificates from your Private PKI to authenticate connections from Cloudflare.

[Global](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/global/), [zone-level](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/zone-level/), and per-hostname AOP are independent configurations. Enabling or disabling one does not affect the others. Per-hostname certificates take precedence over zone-level and global certificates for the specified hostname.

## Before you begin

Warning

It is not possible to set up per-hostname authenticated origin pulls with the Cloudflare-provided certificate used by [global AOP](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/global/). You must upload your own certificate.

Refer to the steps below for an example of how to generate a custom certificate using OpenSSL. The CA root certificate that you use to issue the custom certificate should be the same CA that you will [upload to your origin](#2-configure-origin-to-accept-client-certificates).

OpenSSL example

1. Run the following command to generate a 4096-bit RSA private key, using AES-256 encryption. Enter a passphrase when prompted.

Terminal window

```

openssl genrsa -aes256 -out rootca.key 4096


```

1. Create the CA root certificate. When prompted, fill in the information to be included in the certificate. For the `Common Name` field, use the domain name as value, not the hostname.

Terminal window

```

openssl req -x509 -new -nodes -key rootca.key -sha256 -days 1826 -out rootca.crt


```

1. Create a Certificate Signing Request (CSR). When prompted, fill in the information to be included in the request. For the `Common Name` field, use the hostname as value.

Terminal window

```

openssl req -new -nodes -out cert.csr -newkey rsa:4096 -keyout cert.key


```

1. Sign the certificate using the `rootca.key` and `rootca.crt` created in previous steps.

Terminal window

```

openssl x509 -req -in cert.csr -CA rootca.crt -CAkey rootca.key -CAcreateserial -out cert.crt -days 730 -sha256 -extfile ./cert.v3.ext


```

1. Make sure the certificate extensions file `cert.v3.ext` specifies the following:

```

basicConstraints=CA:FALSE


```

## 1\. Upload custom certificate

* [ Dashboard ](#tab-panel-10495)
* [ API ](#tab-panel-10496)

1. Go to the **Origin Server** page.  
[ Go to **Origin Server** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/origin)
2. Select the **Authenticated Origin Pulls** tab.
3. In the **Per-hostname** section, select **Upload certificate**.
4. Paste the certificate and private key, then select **Continue**.  
Note  
You must upload a [leaf certificate](https://developers.cloudflare.com/ssl/concepts/#chain-of-trust). If you upload a root CA instead, the upload will fail.
5. Review your certificate details, save the certificate ID for future reference, and select **Continue**.
6. On the **Associate Hostnames** page, enter the fully qualified domain name that should use this certificate and select **Add** for each one. You can also skip this step and associate hostnames later.
7. Select **Save** to confirm.

Use the [Upload a Hostname Client Certificate](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/hostname%5Fcertificates/methods/create/) endpoint to upload your custom certificate.

Note

You must upload a [leaf certificate](https://developers.cloudflare.com/ssl/concepts/#chain-of-trust). If you upload a root CA instead, the API will return a `missing leaf certificate` error.

Terminal window

```

MYCERT="$(cat cert.crt|perl -pe 's/\r?\n/\\n/'|sed -e 's/..$//')"

MYKEY="$(cat cert.key|perl -pe 's/\r?\n/\\n/'|sed -e's/..$//')"


request_body=$(< <(cat <<EOF

{

"certificate": "$MYCERT",

"private_key": "$MYKEY",

"bundle_method":"ubiquitous"

}

EOF

))


# Push the certificate


curl --silent \

"https://api.cloudflare.com/client/v4/zones/$ZONEID/origin_tls_client_auth/hostnames/certificates" \

--header "Content-Type: application/json" \

--header "X-Auth-Email: $MYAUTHEMAIL" \

--header "X-Auth-Key: $MYAUTHKEY" \

--data "$request_body"


```

In the API response, save the certificate `id` since it will be required in step 3.

## 2\. Configure origin to accept client certificates

With the certificate installed, set up your origin web server to accept client certificates.

Check the examples below for Apache and NGINX or refer to your origin web server documentation - for example, [HAProxy ↗](https://www.haproxy.com/documentation/hapee/latest/security/authentication/client-certificate-authentication/), [Traefik ↗](https://doc.traefik.io/traefik/https/tls/#client-authentication-mtls), [Caddy ↗](https://caddyserver.com/docs/json/apps/http/servers/tls%5Fconnection%5Fpolicies/client%5Fauthentication/mode/).

Apache example

```

SSLCACertificateFile /path/to/origin-pull-ca.pem


```

For this example, you would have saved your certificate to `/path/to/origin-pull-ca.pem`.

NGINX example

```

ssl_verify_client optional;

ssl_client_certificate /etc/nginx/certs/cloudflare.crt;


```

For this example, you would have saved your certificate to `/etc/nginx/certs/cloudflare.crt`.

At this point, you may also want to enable logging on your origin so that you can verify the configuration is working.

## 3\. Enable Authenticated Origin Pulls for the hostname

* [ Dashboard ](#tab-panel-10493)
* [ API ](#tab-panel-10494)

Note

For per-hostname AOP, the enablement happens as you associate a hostname. If you had already associated hostnames as you uploaded the certificate, you can skip this step.

1. Go to the **Origin Server** page.  
[ Go to **Origin Server** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/origin)
2. Select the **Authenticated Origin Pulls** tab.
3. In the **Per-hostname** section, find the certificate that should be used and associate the hostname with it.

If you had set up logging on your origin during step 2, test and confirm that Authenticated Origin Pulls is working.

Use the [Enable or Disable a Hostname for Client Authentication](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/hostnames/methods/update/) endpoint to enable Authenticated Origin Pulls for specific hostnames.

If you had set up logging on your origin during step 2, test and confirm that Authenticated Origin Pulls is working.

## 4\. Enforce validation check on your origin

Once you can confirm everything is working as expected for your specific origin setup, configure your origin to enforce the authentication.

Apache example

```

SSLVerifyClient require


```

NGINX example

```

ssl_verify_client on;


```

After completing the process, you can use `curl` to send requests directly to your origin IPs, verifying that the requests fail due to certificate validation being enforced.

## 5\. (Optional) Set up expiration alerts

You can configure alerts to receive notifications before your AOP certificates expire.

Hostname-level Authenticated Origin Pulls Certificate Expiration Alert

**Who is it for?**

Customers that upload their own certificate to use with hostname-level Authenticated Origin Pull (AOP) to secure connections from Cloudflare to their origin server. AOP certificate expiration notifications are sent 30 days and 14 days before the certificate expiry.

**Other options / filters**

None.

**Included with**

Authenticated Origin Pull.

**What should you do if you receive one?**

Upload a renewed certificate to use for [hostname-level AOP](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/).

Refer to [Cloudflare Notifications](https://developers.cloudflare.com/notifications/get-started/) for more information on how to set up an alert.

## Further options

Refer to [Manage certificates](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/manage-certificates/) for further options.

To learn how to remove the configuration, refer to [Rollback](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/rollback/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/","name":"Authenticated Origin Pulls (mTLS)"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/set-up/","name":"Setup"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/","name":"Per-hostname"}}]}
```

---

---
title: Roll back per-hostname AOP
description: Roll back per-hostname Authenticated Origin Pulls to zone-level settings.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Roll back per-hostname AOP

If you need to disable or remove your [per-hostname](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/) Authenticated Origin Pulls configuration, follow these steps.

Note

[Global AOP](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/global/), [zone-level AOP](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/zone-level/), and [per-hostname AOP](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/) are three independent configurations. Enabling or disabling one does not affect the others.

1. Use a [PUT request](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/hostnames/methods/update/) to disable Authenticated Origin Pulls on the hostname.  
Required API token permissions  
At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:  
   * `SSL and Certificates Write`  
Enable or Disable a Hostname for Client Authentication  
```  
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/origin_tls_client_auth/hostnames" \  
  --request PUT \  
  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \  
  --json '{  
    "config": [  
        {  
            "enabled": false,  
            "cert_id": "<CERT_ID>",  
            "hostname": "<YOUR_HOSTNAME>"  
        }  
    ]  
  }'  
```
2. (Optional) Use a [GET request](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/hostname%5Fcertificates/methods/list/) to obtain a list of the client certificate IDs. You will need the ID of the certificate you want to remove for the following step.  
Required API token permissions  
At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:  
   * `SSL and Certificates Write`  
   * `SSL and Certificates Read`  
List Certificates  
```  
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/origin_tls_client_auth/hostnames/certificates" \  
  --request GET \  
  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"  
```
3. Use the [Delete hostname client certificate](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/hostname%5Fcertificates/methods/delete/) endpoint to remove the certificate you had uploaded.  
Required API token permissions  
At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:  
   * `SSL and Certificates Write`  
Delete Hostname Client Certificate  
```  
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/origin_tls_client_auth/hostnames/certificates/$CERTIFICATE_ID" \  
  --request DELETE \  
  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"  
```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/","name":"Authenticated Origin Pulls (mTLS)"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/set-up/","name":"Setup"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/set-up/rollback/","name":"Roll back per-hostname AOP"}}]}
```

---

---
title: Zone-level
description: Set up zone-level Authenticated Origin Pulls with a custom certificate.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Zone-level

When you enable zone-level Authenticated Origin Pulls (AOP), all proxied traffic to your zone is authenticated at the origin web server using a certificate that you upload. Unlike [global AOP](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/global/), which uses a Cloudflare-provided certificate shared across all accounts, zone-level AOP uses your own certificate for stricter security.

[Global](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/global/), zone-level, and [per-hostname](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/) AOP are independent configurations. Enabling or disabling one does not affect the others.

## Before you begin

Make sure your zone is using an [SSL/TLS encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/) of **Full** or higher.

Warning

Zone-level AOP certificates are also applied to [custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/) configured on a Cloudflare for SaaS zone. If you need a different AOP certificate for different custom hostnames, use [per-hostname AOP](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/per-hostname/).

Zone-level AOP requires you to upload your own certificate. Refer to the steps below for an example of how to generate a custom certificate using OpenSSL. The CA root certificate that you use to issue the custom certificate should be the same CA that you will [upload to your origin](#3-configure-origin-to-accept-client-certificates).

OpenSSL example

1. Run the following command to generate a 4096-bit RSA private key, using AES-256 encryption. Enter a passphrase when prompted.

Terminal window

```

openssl genrsa -aes256 -out rootca.key 4096


```

1. Create the CA root certificate. When prompted, fill in the information to be included in the certificate. For the `Common Name` field, use the domain name as value, not the hostname.

Terminal window

```

openssl req -x509 -new -nodes -key rootca.key -sha256 -days 1826 -out rootca.crt


```

1. Create a Certificate Signing Request (CSR). When prompted, fill in the information to be included in the request. For the `Common Name` field, use the hostname as value.

Terminal window

```

openssl req -new -nodes -out cert.csr -newkey rsa:4096 -keyout cert.key


```

1. Sign the certificate using the `rootca.key` and `rootca.crt` created in previous steps.

Terminal window

```

openssl x509 -req -in cert.csr -CA rootca.crt -CAkey rootca.key -CAcreateserial -out cert.crt -days 730 -sha256 -extfile ./cert.v3.ext


```

1. Make sure the certificate extensions file `cert.v3.ext` specifies the following:

```

basicConstraints=CA:FALSE


```

## 1\. Upload your certificate to Cloudflare

* [ Dashboard ](#tab-panel-10497)
* [ API ](#tab-panel-10498)

1. Go to the **Origin Server** page.  
[ Go to **Origin Server** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/origin)
2. Select the **Authenticated Origin Pulls** tab.
3. In the **Zone-level** section, select **Upload certificate**.
4. Paste the certificate and private key, then select **Continue**.  
Note  
You must upload a [leaf certificate](https://developers.cloudflare.com/ssl/concepts/#chain-of-trust). If you upload a root CA instead, the upload will fail.
5. Review your certificate details, save the certificate ID for future reference, and select **Done**.

Use the [Upload a zone-level client certificate](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/zone%5Fcertificates/methods/create/) endpoint to upload your certificate.

Note

You must upload a [leaf certificate](https://developers.cloudflare.com/ssl/concepts/#chain-of-trust). If you upload a root CA instead, the API will return a `missing leaf certificate` error.

## 2\. Upload the CA certificate to your origin

Upload the CA root certificate used to sign your client certificate to your origin server. Your origin will use this CA certificate to verify the client certificate presented by Cloudflare.

## 3\. Configure origin to accept client certificates

With the certificate installed, set up your origin web server to accept client certificates.

Check the examples below for Apache and NGINX or refer to your origin web server documentation - for example, [HAProxy ↗](https://www.haproxy.com/documentation/hapee/latest/security/authentication/client-certificate-authentication/), [Traefik ↗](https://doc.traefik.io/traefik/https/tls/#client-authentication-mtls), [Caddy ↗](https://caddyserver.com/docs/json/apps/http/servers/tls%5Fconnection%5Fpolicies/client%5Fauthentication/mode/).

Apache example

```

SSLCACertificateFile /path/to/origin-pull-ca.pem


```

For this example, you would have saved your certificate to `/path/to/origin-pull-ca.pem`.

NGINX example

```

ssl_verify_client optional;

ssl_client_certificate /etc/nginx/certs/cloudflare.crt;


```

For this example, you would have saved your certificate to `/etc/nginx/certs/cloudflare.crt`.

At this point, you may also want to enable logging on your origin so that you can verify the configuration is working.

## 4\. Enable zone-level Authenticated Origin Pulls

* [ Dashboard ](#tab-panel-10499)
* [ API ](#tab-panel-10500)

1. Go to the **Origin Server** page.  
[ Go to **Origin Server** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/origin)
2. Select the **Authenticated Origin Pulls** tab.
3. In the **Zone-level** section, switch the toggle to **On**.

Use the [Set Enablement for Zone](https://developers.cloudflare.com/api/resources/origin%5Ftls%5Fclient%5Fauth/subresources/settings/methods/update/) endpoint to enable zone-level Authenticated Origin Pulls.

Warning

This endpoint is separate from the [global AOP toggle](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/global/), which uses the zone settings `tls_client_auth` setting. Make sure you use the correct endpoint for the configuration you intend.

## 5\. Enforce validation check on your origin

Once you can confirm everything is working as expected for your specific origin setup, configure your origin to enforce the authentication.

Apache example

```

SSLVerifyClient require


```

NGINX example

```

ssl_verify_client on;


```

After completing the process, you can use `curl` to send requests directly to your origin IPs, verifying that the requests fail due to certificate validation being enforced.

## 6\. (Optional) Set up expiration alerts

You can configure alerts to receive notifications before your AOP certificates expire.

Zone-level Authenticated Origin Pulls Certificate Expiration Alert

**Who is it for?**

Customers that upload their own certificate to use with zone-level Authenticated Origin Pull (AOP) to secure connections from Cloudflare to their origin server. AOP certificate expiration notifications are sent 30 days and 14 days before the certificate expiry.

**Other options / filters**

None.

**Included with**

Authenticated Origin Pull.

**What should you do if you receive one?**

Upload a renewed certificate to use for [zone-level AOP](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/).

Refer to [Cloudflare Notifications](https://developers.cloudflare.com/notifications/get-started/) for more information on how to set up an alert.

## Further options

Refer to [Manage certificates](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/manage-certificates/) for further options.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/","name":"Authenticated Origin Pulls (mTLS)"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/set-up/","name":"Setup"}},{"@type":"ListItem","position":6,"item":{"@id":"/ssl/origin-configuration/authenticated-origin-pull/set-up/zone-level/","name":"Zone-level"}}]}
```

---

---
title: Cipher suites
description: Review a list of cipher suites that Cloudflare presents to origins during an SSL/TLS handshake.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cipher suites

Refer to the following list to know what cipher suites Cloudflare presents to origin servers during an SSL/TLS handshake.

Note

Refer to [cipher suites supported at Cloudflare's global network](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/supported-cipher-suites/) to know what cipher suites Cloudflare presents to browsers and other user agents.

The list order is based on how the cipher suites appear in the [ClientHello ↗](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/#:~:text=client%20hello), communicating Cloudflare's preference.

## Supported cipher suites by protocol

| Cipher name                                           | TLS 1.0 | TLS 1.1 | TLS 1.2 | TLS 1.3 |
| ----------------------------------------------------- | ------- | ------- | ------- | ------- |
| AEAD-AES128-GCM-SHA256 [1](#user-content-fn-1)        | ❌       | ❌       | ❌       | ✅       |
| AEAD-AES256-GCM-SHA384 [1](#user-content-fn-1)        | ❌       | ❌       | ❌       | ✅       |
| AEAD-CHACHA20-POLY1305-SHA256 [1](#user-content-fn-1) | ❌       | ❌       | ❌       | ✅       |
| ECDHE-ECDSA-AES128-GCM-SHA256                         | ❌       | ❌       | ✅       | ❌       |
| ECDHE-RSA-AES128-GCM-SHA256                           | ❌       | ❌       | ✅       | ❌       |
| ECDHE-RSA-AES128-SHA                                  | ✅       | ✅       | ✅       | ❌       |
| AES128-GCM-SHA256                                     | ❌       | ❌       | ✅       | ❌       |
| AES128-SHA                                            | ✅       | ✅       | ✅       | ❌       |
| ECDHE-ECDSA-AES256-GCM-SHA384                         | ❌       | ❌       | ✅       | ❌       |
| ECDHE-RSA-AES256-GCM-SHA384                           | ❌       | ❌       | ✅       | ❌       |
| ECDHE-RSA-AES256-SHA384                               | ❌       | ❌       | ✅       | ❌       |
| AES256-SHA                                            | ✅       | ✅       | ✅       | ❌       |
| DES-CBC3-SHA                                          | ✅       | ❌       | ❌       | ❌       |

### TLS 1.3 cipher suites

Although TLS 1.3 uses the same cipher suite space as previous versions of TLS, TLS 1.3 cipher suites are defined differently, only specifying the symmetric ciphers, and cannot be used for TLS 1.2 ([RFC 8446 ↗](https://www.rfc-editor.org/rfc/rfc8446.html)).

Similarly, TLS 1.2 and lower cipher suites cannot be used with TLS 1.3\. BoringSSL also hard-codes cipher preferences in the order above for TLS 1.3.

Based on BoringSSL, Cloudflare system will return the names listed above. However, the corresponding names defined in [RFC 8446 ↗](https://www.rfc-editor.org/rfc/rfc8446.html) are the following:

* `TLS_AES_128_GCM_SHA256`
* `TLS_AES_256_GCM_SHA384`
* `TLS_CHACHA20_POLY1305_SHA256`

## Match on origin

Cloudflare will present the cipher suites to your origin and your server will select whichever cipher suite it prefers.

However, if you want to ensure that your origin server supports the same cipher suites that Cloudflare supports at our global network and you use [NGINX ↗](https://en.wikipedia.org/wiki/Nginx) for TLS termination on your origin, you can apply the following configuration:

```

ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

ssl_ecdh_curve X25519:P-256:P-384;

ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305:ECDHE+AES128:RSA+AES128:ECDHE+AES256:RSA+AES256:ECDHE+3DES:RSA+3DES;

ssl_prefer_server_ciphers on;


```

## Footnotes

1. Refer to [TLS 1.3 cipher suites](#tls-13-cipher-suites) for details. [↩](#user-content-fnref-1) [↩2](#user-content-fnref-1-2) [↩3](#user-content-fnref-1-3)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/cipher-suites/","name":"Cipher suites"}}]}
```

---

---
title: Custom Origin Trust Store
description: Custom Origin Trust Store allows you to upload certificate authorities (CAs) that Cloudflare will use to authenticate connections to your origin server.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Custom Origin Trust Store

By default, Cloudflare's global network maintains [a list of publicly trusted certificate authorities ↗](https://github.com/cloudflare/cfssl%5Ftrust). This means that when using [Full (strict) encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/), Cloudflare will only trust origin server certificates issued by a CA included in this trust store.

Custom Origin Trust Store allows you to upload certificate authorities (CAs) that Cloudflare will use to authenticate connections to your origin server. Use this feature to override the default trust store with your preferred CA or CAs.

  
When a CA has been uploaded to Custom Origin Trust Store, Cloudflare will ignore all default publicly trusted CAs and exclusively use the CA or CAs that have been uploaded to authenticate the origin server.

## Availability

To get access to Custom Origin Trust Store, [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) must be enabled on the zone.

## How to

To manage origin trust stores in the dashboard:

1. Go to the **Origin Server** page.  
[ Go to **Origin Server** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/origin)
2. Select the **Custom Origin Trust Store** tab.
3. Select **Upload trust store** to add a CA certificate, or use the table to manage existing trust stores.

To manage origin trust stores using the API, refer to the [API commands](#api-commands).

## Limitations

With [Full (strict) encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/) enabled, if your uploaded CA expires and no alternative CAs are valid within the trust store, Cloudflare will not be able to properly authenticate connections to the origin server.

## API commands

#### List Custom Origin Trust Store Details

* API documentation: [List Custom Origin Trust Store Details](https://developers.cloudflare.com/api/resources/acm/subresources/custom%5Ftrust%5Fstore/methods/list/)
* Method: `GET`
* Endpoint: `/zones/$ZONE_ID/acm/custom_trust_store`

#### Custom Origin Trust Store Details

* API documentation: [Custom Origin Trust Store Details](https://developers.cloudflare.com/api/resources/acm/subresources/custom%5Ftrust%5Fstore/methods/get/)
* Method: `GET`
* Endpoint: `/zones/$ZONE_ID/acm/custom_trust_store/$CUSTOM_ORIGIN_TRUST_STORE_ID`  
Note  
The `$CUSTOM_ORIGIN_TRUST_STORE_ID` can be found via the [List command](#list-custom-origin-trust-store-details).

#### Upload Custom Origin Trust Store

* API documentation: [Upload Custom Origin Trust Store](https://developers.cloudflare.com/api/resources/acm/subresources/custom%5Ftrust%5Fstore/methods/create/)
* Method: `POST`
* Endpoint: `/zones/$ZONE_ID/acm/custom_trust_store`

#### Delete Custom Origin Trust Store

* API documentation: [Delete Custom Origin Trust Store](https://developers.cloudflare.com/api/resources/acm/subresources/custom%5Ftrust%5Fstore/methods/delete/)
* Method: `DELETE`
* Endpoint: `/zones/$ZONE_ID/acm/custom_trust_store/$CUSTOM_ORIGIN_TRUST_STORE_ID`  
Note  
The `$CUSTOM_ORIGIN_TRUST_STORE_ID` can be found via the [List command](#list-custom-origin-trust-store-details).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/custom-origin-trust-store/","name":"Custom Origin Trust Store"}}]}
```

---

---
title: Cloudflare origin CA
description: Encrypt traffic between Cloudflare and your origin web server and reduce origin bandwidth consumption.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare origin CA

If your origin only receives traffic from proxied records, use Cloudflare origin CA certificates to encrypt traffic between Cloudflare and your origin web server and reduce bandwidth consumption. Once deployed, these certificates are compatible with [Strict SSL mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/).

For more background information on origin CA certificates, refer to the [introductory blog post ↗](https://blog.cloudflare.com/cloudflare-ca-encryption-origin/).

API Access required

Users who do not have [**API Access** ↗](https://dash.cloudflare.com/?to=/:account/members) will receive an error while trying to create or revoke an origin CA certificate. Refer to [Troubleshooting](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/troubleshooting/#this-zone-is-either-not-part-of-your-account-or-you-do-not-have-access-to-it) for guidance.

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

Note

Using Cloudflare origin CA certificates does not prevent you from using [delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/).

Known limitation

Cloudflare does not currently send expiration notifications for origin CA certificates. If you rely on long-lived origin CA certificates, track their expiration in your own certificate inventory or monitoring system.

---

## Deploy an Origin CA certificate

### 1\. Create an Origin CA certificate

To create an Origin CA certificate in the dashboard:

1. Go to the **Origin Server** page.  
[ Go to **Origin Server** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/origin)
2. On the **Origin Certificates** tab, select **Create Certificate**.
3. Choose either:  
   * **Generate private key and CSR with Cloudflare**: Private key type can be RSA or ECC.  
   * **Use my private key and CSR**: Paste the Certificate Signing Request into the text field.
4. List the [hostnames (including wildcards)](#hostname-and-wildcard-coverage) the certificate should protect with SSL encryption. The zone apex and first level wildcard hostname are included by default.
5. Choose a **Certificate Validity** period.
6. Select **Create**.
7. Choose the **Key Format**:  
   * Servers using OpenSSL — like Apache and NGINX — generally expect PEM files (Base64-encoded ASCII), but also work with binary DER files.  
   * Servers using Windows and Apache Tomcat require PKCS#7 (a `.p7b` file).
8. Copy the signed **Origin Certificate** and **Private Key** into separate files. For security reasons, you cannot see the **Private Key** after you exit this screen.
9. Select **OK**.

Note

For details about working with certificates programmatically, refer to [API calls](#api-calls).

### 2\. Install Origin CA certificate on origin server

To add an Origin CA certificate to your origin web server

1. Upload the Origin CA certificate (created in [Step 1](#1-create-an-origin-ca-certificate)) to your origin web server.
2. Update your web server configuration:
* [Apache httpd ↗](https://www.digicert.com/kb/csr-ssl-installation/apache-openssl.htm)
* [GoDaddy Hosting ↗](https://www.digitalcandy.agency/website-tips/cloudflare-origin-ca-free-ssl-installation-on-godaddy/)
* [Microsoft IIS 7 ↗](https://knowledge.digicert.com/tutorials/iis7-create-csr-install-ssl-certificate)
* [Microsoft IIS 8 and 8.5 ↗](https://knowledge.digicert.com/tutorials/iis-8-create-csr-install-ssl-certificate)
* [Microsoft IIS 10 ↗](https://www.digicert.com/kb/csr-creation-ssl-installation-iis-10.htm)
* [NGINX ↗](https://www.digicert.com/kb/csr-ssl-installation/nginx-openssl.htm)
* [Apache Tomcat ↗](https://knowledge.digicert.com/tutorials/tomcat-install-your-ssl-certificate-on-a-tomcat-server)
* [Amazon Web Services ↗](https://knowledge.digicert.com/tutorials/amazon-aws-create-csr-install-ssl-certificate)
* [Apache cPanel ↗](https://www.digicert.com/kb/ssl-certificate-installation-apache-cpanel.htm)
* [Ubuntu Server with Apache2 ↗](https://www.digicert.com/kb/csr-ssl-installation/ubuntu-server-with-apache2-openssl.htm#ssl%5Fcertificate%5Finstall)

Note

If you do not see your server in the list above, search the [DigiCert documentation ↗](https://www.digicert.com/search-results) or contact your hosting provider, web admin, or server vendor.

1. (Required for some) Upload the [Cloudflare CA root certificate](#cloudflare-origin-ca-root-certificate) to your origin server. This can also be referred to as the certificate chain.
2. Enable SSL and port `443` at your origin web server.

### 3\. Change SSL/TLS mode

After you have installed the Origin CA certificate on your origin web server, update the SSL/TLS encryption mode for your application.

If all your origin hosts are protected by Origin CA certificates or publicly trusted certificates:

1. Go to the **SSL/TLS** overview page.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls)
2. For **SSL/TLS encryption mode**, select **Full (strict)**.

If you have origin hosts that are not protected by certificates, set the **SSL/TLS encryption** mode for a specific application to **Full (strict)** by using a [Page Rule](https://developers.cloudflare.com/rules/page-rules/).

Warning

Site visitors may see untrusted certificate errors if you [pause Cloudflare](https://developers.cloudflare.com/fundamentals/manage-domains/pause-cloudflare/) or disable proxying on subdomains that use Cloudflare origin CA certificates. These certificates only encrypt traffic between Cloudflare and your origin server, not traffic from client browsers to your origin.

## Revoke an Origin CA certificate

If you misplace your key material or do not want a certificate to be trusted, you may want to revoke your certificate. You cannot undo this process.

To prevent visitors from seeing warnings about an insecure certificate, you may want to set your [SSL/TLS encryption](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/) to **Full** or **Flexible** before revoking your certificate. Do this globally via the [Cloudflare dashboard ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls) or for a specific hostname via a [Page Rule](https://developers.cloudflare.com/rules/page-rules/).

To revoke a certificate:

1. Go to the **Origin Server** page.  
[ Go to **Origin Server** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/origin)
2. On the **Origin Certificates** tab, choose a certificate.
3. Select **Revoke**.

## Additional details

### Cloudflare Origin CA root certificate

Some origin web servers require upload of the Cloudflare Origin CA root certificate or certificate chain. Use the following links to download either an ECC or an RSA version and upload to your origin web server:

* [Cloudflare Origin ECC PEM](https://developers.cloudflare.com/ssl/static/origin%5Fca%5Fecc%5Froot.pem) (do not use with Apache cPanel)
* [Cloudflare Origin RSA PEM](https://developers.cloudflare.com/ssl/static/origin%5Fca%5Frsa%5Froot.pem)

### Hostname and wildcard coverage

Certificates may be generated with up to 200 individual Subject Alternative Names (SANs). A SAN can take the form of a fully-qualified domain name (`www.example.com`) or a wildcard (`*.example.com`). You cannot use IP addresses as SANs on Cloudflare origin CA certificates.

Wildcards may only cover one level, but can be used multiple times on the same certificate for broader coverage (for example, `*.example.com` and `*.secure.example.com` may co-exist).

## API calls

To automate processes involving Origin CA certificates, use the following API calls. To authenticate, use an [API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) with **Permissions** that include `Zone`\-`SSL and Certificates`\-`Edit`.

| Operation                                                                                                        | Method | Endpoint                           |
| ---------------------------------------------------------------------------------------------------------------- | ------ | ---------------------------------- |
| [List certificates](https://developers.cloudflare.com/api/resources/origin%5Fca%5Fcertificates/methods/list/)    | GET    | certificates?zone\_id=<<ZONE\_ID>> |
| [Create certificate](https://developers.cloudflare.com/api/resources/origin%5Fca%5Fcertificates/methods/create/) | POST   | certificates                       |
| [Get certificate](https://developers.cloudflare.com/api/resources/origin%5Fca%5Fcertificates/methods/get/)       | GET    | certificates/<<ID>>                |
| [Revoke certificate](https://developers.cloudflare.com/api/resources/origin%5Fca%5Fcertificates/methods/delete/) | DELETE | certificates/<<ID>>                |

## Troubleshooting

If you find `NET::ERR_CERT_AUTHORITY_INVALID` or other issues after setting up Cloudflare origin CA, refer to [troubleshooting](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/troubleshooting/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/origin-ca/","name":"Cloudflare origin CA"}}]}
```

---

---
title: Troubleshooting Cloudflare origin CA
description: Troubleshoot issues like NET::ERR_CERT_AUTHORITY_INVALID when using Cloudflare origin CA.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting Cloudflare origin CA

Consider the following common issues and troubleshooting steps when using [Cloudflare origin CA](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/).

## NET::ERR\_CERT\_AUTHORITY\_INVALID

### Cause

Site visitors may see untrusted certificate errors if you [pause Cloudflare](https://developers.cloudflare.com/fundamentals/manage-domains/pause-cloudflare/) or disable proxying on subdomains that use Cloudflare origin CA certificates. These certificates only encrypt traffic between Cloudflare and your origin server, not traffic from client browsers to your origin.

This also means that SSL Labs or similar SSL validators are expected to flag the certificate as invalid.

### Solutions

* Make sure the [proxy status](https://developers.cloudflare.com/dns/proxy-status/) of your DNS records and any [page rules](https://developers.cloudflare.com/rules/page-rules/) (if existing) are set up correctly. If so, you can try to turn proxying off and then on again and wait a few minutes.
* If you must have direct connections between clients and your origin server, consider installing a publicly trusted certificate at your origin instead. This process is done outside of Cloudflare, where you should issue the certificate directly from a certificate authority (CA) of your choice. You can still use Full (strict) [encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/), as long as the CA is listed on the [Cloudflare trust store ↗](https://github.com/cloudflare/cfssl%5Ftrust).

## The issuer of this certificate could not be found

### Cause

Some origin web servers require that you upload the Cloudflare origin CA root certificate or certificate chain.

### Solution

Use the following links to download either an ECC or an RSA version and upload to your origin web server:

* [Cloudflare Origin ECC PEM](https://developers.cloudflare.com/ssl/static/origin%5Fca%5Fecc%5Froot.pem) (do not use with Apache cPanel)
* [Cloudflare Origin RSA PEM](https://developers.cloudflare.com/ssl/static/origin%5Fca%5Frsa%5Froot.pem)

## The certificate is not trusted in all web browsers

### Cause

Apache cPanel requires that you upload the Cloudflare origin CA root certificate or certificate chain.

### Solution

Use the following link to download an RSA version of the root certificate and upload it to your origin web server:

* [Cloudflare Origin RSA PEM](https://developers.cloudflare.com/ssl/static/origin%5Fca%5Frsa%5Froot.pem)

## This zone is either not part of your account, or you do not have access to it

When trying to generate an Origin CA on the dashboard, you find the error `Failed to validate requested hostname <hostname>: This zone is either not part of your account, or you do not have access to it`.

### Cause

This is a known issue where, whilst being created on the Cloudflare dashboard, Origin CA requires API access for the user creating the origin certificate. If the user does not have **API Access**, this error is returned.

### Solution

Make sure that the user creating the certificate has access to the API. You can check in the account **Members** page.

[ Go to **Members** ](https://dash.cloudflare.com/?to=/:account/members) 
* The default setting for the account is specified in the card **Enable API Access**.
* Specific user API Access (which can override the default setting) is presented after selecting the user in the list of members.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/origin-ca/","name":"Cloudflare origin CA"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/origin-configuration/origin-ca/troubleshooting/","name":"Troubleshooting Cloudflare origin CA"}}]}
```

---

---
title: Encryption modes
description: Encryption modes allow you to control how Cloudflare connects to your origin web server and how certificates presented by your origin are validated.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Encryption modes

Your zone's **SSL/TLS Encryption Mode** controls how Cloudflare manages two connections: one between your visitors and Cloudflare, and the other between Cloudflare and your origin server.

flowchart LR
    accTitle: SSL/TLS Encryption mode
    A[Browser] <--Connection 1--> B((Cloudflare))<--Connection 2--> C[(Origin server)]

  
If possible, Cloudflare strongly recommends using [**Full**](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full/) or [**Full (strict)**](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/) modes to prevent malicious connections to your origin.

For more details on how encryption modes fit into the bigger picture of Cloudflare SSL/TLS protection, refer to [Concepts](https://developers.cloudflare.com/ssl/concepts/#ssltls-certificate).

## Available encryption modes

[Automatic SSL/TLS](#automatic-ssltls-default) relies on the probes developed for the SSL/TLS Recommender to determine what encryption mode is the most secure and safest for a website to be set to. If there is a more secure option for your website (based on your origin certification or capabilities), Automatic SSL/TLS will find it and apply it for your domain. The other option, [Custom SSL/TLS](#custom-ssltls), will work exactly like the setting the encryption mode does today.

Note

We are gradually rolling out the new [Automated SSL/TLS feature](#automatic-ssltls-default).

If your zone has not been migrated yet, you will only have [Custom SSL/TLS](#custom-ssltls) options in your dashboard.

To understand how the various encryption modes affect your cache, refer to the section on [Impact of SSL setting on cache behavior](https://developers.cloudflare.com/cache/how-to/cache-keys/#impact-of-ssl-settings-on-cache-behavior).

### Automatic SSL/TLS (default)

Automatic SSL/TLS leverages advanced methods developed by the SSL/TLS Recommender to select the most secure encryption mode for your website. The Recommender crawls your site using the Cloudflare-SSLDetector user agent, recognized as a trusted bot by Cloudflare, and bypasses `robots.txt` rules (except those that specifically target it) to ensure accuracy. It downloads content from your origin server over both HTTP and HTTPS, then applies a content similarity algorithm to assess consistency. By understanding your current SSL/TLS encryption mode and evaluating your origin's certification and capabilities, the Recommender can automatically adjust settings to maintain the highest security for your domain.

Note

Automatic SSL/TLS will not change your setting to a less secure encryption mode. For example, if your origin certificate expires, the encryption mode will not change from **Full (strict)** to **Full**. You must ensure the validity of your origin SSL/TLS configuration at all times.

Automatic upgrades are applied gradually. Automatic SSL/TLS begins to upgrade the domain by starting with just 1% of its traffic. If no issues are found, the new SSL/TLS encryption mode is applied to traffic in 10% increments until 100% of traffic uses the recommended mode. If origin connectivity fails during this process, Cloudflare aborts the upgrade, immediately rolls traffic back to the previous mode, and logs the failure. Once 100% of traffic has been successfully upgraded with no TLS-related errors, the domain's SSL/TLS setting is permanently updated.

Flexible → Full/Strict transitions are handled with extra caution since the origin scheme change (HTTP → HTTPS) alters cache keys. In this case, the ramp-up may proceed more slowly to allow cache warm-up before resuming standard increments.

#### Additional details

* **Scan frequency**: Automatic scans currently occur approximately once per month, though they may happen more frequently in some cases (for example, configuration changes or upgrades). Scans stop when:  
   * The site is already using the most secure mode (for example, **Full (strict)**), or  
   * You switch from auto mode to **Custom SSL/TLS**.
* **Error checking before upgrades**: To prevent disruptions, Cloudflare checks for `5XX` errors (like `502` or `503`) and evaluates whether the HTTP and HTTPS content is consistent before upgrading a zone's encryption mode.
* **Upgrade notifications**: Cloudflare sends weekly digest emails listing which zones have been upgraded. These emails are currently sent to Super Admins only.

#### Opt out single zone

If you want to opt a zone out via the API, you can make this API call on or before the grace period expiration date.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Zone Settings Write`

Edit zone setting

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/ssl_automatic_mode" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "value": "custom"

  }'


```

#### Opt out multiple zones

If you wanted to opt out multiple zones:

1. Create an API token with the following permissions:  
   * `Zone - Zone - Read`  
   * `Zone - Zone Settings - Read`  
   * `Zone - Zone Settings - Edit`
2. Make a [GET request](https://developers.cloudflare.com/api/resources/zones/methods/list/) to get a list of zones (you can filter this list by `account.id`).  
Terminal window  
```  
curl 'https://api.cloudflare.com/client/v4/zones?account.id=<ACCOUNT_ID>' \  
--header 'Authorization: Bearer <CF_API_TOKEN>' \  
--header 'Content-Type: application/json'  
```
3. Create a list of zone IDs you want to opt-out with each zone ID on a separate line (newline separate), stored in a file such as `zones.txt`.
4. Create a bash script for `opt-out-multiple-zones.sh` and add the following. Add `zones.txt` to the same directory or update the path accordingly.  
opt-out-multiple-zones.sh  
```  
for zoneID in $(cat zone.txt); do  
  printf "Opting out ${zoneID}:\n"  
  curl --request PATCH \  
    --url https://api.cloudflare.com/client/v4/zones/$zoneID/settings/ssl_automatic_mode \  
    --header 'Authorization: Bearer <CF_API_TOKEN>' \  
    --header 'Content-Type: application/json' \  
    --data '{"value":"custom"}'  
  printf "\n\n"  
done  
```
5. Open your command line and run:  
Terminal window  
```  
bash opt-out-multiple-zones.sh  
```

### Custom SSL/TLS

To use Custom SSL/TLS, select the custom option (if you prefer to manually set the encryption mode instead of using [Automatic SSL/TLS](#automatic-ssltls-default)):

* [ Off (no encryption) ](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/off/) :  No encryption is used for traffic between browsers and Cloudflare or between Cloudflare and origins. Everything is cleartext HTTP.
* [ Flexible ](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/flexible/) :  Traffic from browsers to Cloudflare can be encrypted via HTTPS, but traffic from Cloudflare to the origin server is not. This mode is common for origins that do not support TLS, though upgrading the origin configuration is recommended whenever possible.
* [ Full ](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full/) :  Cloudflare matches the browser request protocol when connecting to the origin. If the browser uses HTTP, Cloudflare connects to the origin via HTTP; if HTTPS, Cloudflare uses HTTPS without validating the origin’s certificate. This mode is common for origins that use self-signed or otherwise invalid certificates.
* [ Full (strict) ](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/) :  Similar to Full Mode, but with added validation of the origin server’s certificate, which can be issued by a public CA like Let’s Encrypt or by Cloudflare Origin CA.
* [ Strict (SSL-Only Origin Pull) ](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/ssl-only-origin-pull/) :  Regardless of whether the browser-to-Cloudflare connection uses HTTP or HTTPS, Cloudflare always connects to the origin over HTTPS with certificate validation.

## Update your encryption mode

* [ Dashboard ](#tab-panel-10501)
* [ API ](#tab-panel-10502)

To change your encryption mode in the dashboard:

1. In the Cloudflare dashboard, go to the **SSL/TLS Overview** page.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls)
2. Choose an encryption mode.

To adjust your encryption mode with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `ssl` as the setting name in the URI path, and the `value` parameter set to your desired setting (`off`, `flexible`, `full`, `strict`, or `origin_pull`).

Note

To use this feature on specific hostnames - instead of across your entire zone - use a [configuration rule](https://developers.cloudflare.com/rules/configuration-rules/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/ssl-modes/","name":"Encryption modes"}}]}
```

---

---
title: Flexible
description: Traffic from browsers to Cloudflare can be encrypted via HTTPS, but traffic from Cloudflare to the origin server is not. This mode is common for origins that do not support TLS, though upgrading the origin configuration is recommended whenever possible.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Flexible

Setting your encryption mode to **Flexible** makes your site partially secure. Cloudflare allows HTTPS connections between your visitor and Cloudflare, but all connections between Cloudflare and your origin are made through HTTP. As a result, an SSL certificate is not required on your origin.

flowchart LR
    accTitle: Flexible SSL/TLS Encryption
    accDescr: With an encryption mode of Flexible, your application encrypts traffic between the visitor and Cloudflare, but not between Cloudflare and your server.
    A[Browser] <--Encrypted--> B((Cloudflare))<--Unencrypted--> C[(Origin server)]

## Use when

Choose this option when you cannot set up an SSL certificate on your origin or your origin does not support SSL/TLS.

## Required setup

### Prerequisites

Depending on your origin configuration, you may have to adjust settings to avoid [Mixed Content errors](https://developers.cloudflare.com/ssl/troubleshooting/mixed-content-errors/) or [redirect loops](https://developers.cloudflare.com/ssl/troubleshooting/too-many-redirects/).

### Process

* [ Dashboard ](#tab-panel-10503)
* [ API ](#tab-panel-10504)

To change your encryption mode in the dashboard:

1. In the Cloudflare dashboard, go to the **SSL/TLS Overview** page.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls)
2. Choose an encryption mode.

To adjust your encryption mode with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `ssl` as the setting name in the URI path, and the `value` parameter set to your desired setting (`off`, `flexible`, `full`, `strict`, or `origin_pull`).

## Limitations

Flexible mode is only supported for HTTPS connections on port 443 (default port). Other ports using HTTPS will fall back to [**Full** mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full/).

If your application contains sensitive information (personalized data, user login), use [**Full**](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full/) or [**Full (Strict)**](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/) modes instead.

[Authenticated Origin Pull](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/) does not work when your [**SSL/TLS encryption mode**](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/) is set to **Off** or **Flexible**.

  

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/ssl-modes/","name":"Encryption modes"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/origin-configuration/ssl-modes/flexible/","name":"Flexible"}}]}
```

---

---
title: Full
description: Cloudflare matches the browser request protocol when connecting to the origin. If the browser uses HTTP, Cloudflare connects to the origin via HTTP; if HTTPS, Cloudflare uses HTTPS without validating the origin’s certificate. This mode is common for origins that use self-signed or otherwise invalid certificates.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Full

When you set your encryption mode to **Full**, Cloudflare allows HTTPS connections between your visitor and Cloudflare and makes connections to the origin using the scheme requested by the visitor. If your visitor uses `http`, then Cloudflare connects to the origin using plaintext HTTP and vice versa.

## Use when

Choose **Full** mode when your origin can support an SSL certification, but — for various reasons — it cannot support a valid, publicly trusted certificate.

Note

In addition to **Full** encryption, you can also set up [Authenticated Origin Pulls](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/) to ensure all requests to your origin are evaluated before receiving a response.

## Required setup

### Prerequisites

Before enabling **Full** mode, make sure your origin allows HTTPS connections on port 443 and presents a certificate (self-signed, [Cloudflare Origin CA](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/), or purchased from a Certificate Authority). Otherwise, your visitors may experience a [525 error](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-525/).

Depending on your origin configuration, you may have to adjust settings to avoid [Mixed Content errors](https://developers.cloudflare.com/ssl/troubleshooting/mixed-content-errors/) or [redirect loops](https://developers.cloudflare.com/ssl/troubleshooting/too-many-redirects/).

### Process

* [ Dashboard ](#tab-panel-10505)
* [ API ](#tab-panel-10506)

To change your encryption mode in the dashboard:

1. In the Cloudflare dashboard, go to the **SSL/TLS Overview** page.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls)
2. Choose an encryption mode.

To adjust your encryption mode with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `ssl` as the setting name in the URI path, and the `value` parameter set to your desired setting (`off`, `flexible`, `full`, `strict`, or `origin_pull`).

## Limitations

The certificate presented by the origin will **not be validated in any way**. It can be expired, self-signed, or not even have a matching CN/SAN entry for the hostname requested.

Without using [**Full (strict)**](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/), a malicious party could technically hijack the connection and present their own certificate.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/ssl-modes/","name":"Encryption modes"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/origin-configuration/ssl-modes/full/","name":"Full"}}]}
```

---

---
title: Full (strict)
description: Similar to Full Mode, but with added validation of the origin server’s certificate, which can be issued by a public CA like Let’s Encrypt or by Cloudflare Origin CA.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Full (strict)

When you set your encryption mode to **Full (strict)**, Cloudflare does everything in [Full mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full/) but also enforces more stringent requirements for origin certificates.

flowchart LR
    accTitle: Full - Strict SSL/TLS Encryption
    accDescr: With an encryption mode of Full (strict), your application encrypts traffic going to and coming from Cloudflare.
    A[Browser] <--Encrypted--> B((Cloudflare))<--Encrypted--> C[("Origin server (verified) #9989;")]

## Use when

For the best security, choose **Full (strict)** mode whenever possible (unless you are an [Enterprise customer](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/ssl-only-origin-pull/)).

Your origin needs to be able to support an SSL certificate that is:

* Unexpired, meaning the certificate presents `notBeforeDate < now() < notAfterDate`.
* Issued by a [publicly trusted certificate authority ↗](https://github.com/cloudflare/cfssl%5Ftrust) or [Cloudflare’s Origin CA](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/).
* Contains a Common Name (CN) or Subject Alternative Name (SAN) that matches the requested or target hostname.

Note

In addition to **Full (strict)** encryption, you can also set up [Authenticated Origin Pulls](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/) to ensure all requests to your origin are evaluated before receiving a response.

## Required setup

### Prerequisites

Before enabling **Full (strict)** mode, make sure your origin:

* Allows HTTPS connections on port `443`.
* Presents a certificate matching the requirements above.

Otherwise, your visitors may experience a [526 error](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-526/).

### Process

* [ Dashboard ](#tab-panel-10507)
* [ API ](#tab-panel-10508)

To change your encryption mode in the dashboard:

1. In the Cloudflare dashboard, go to the **SSL/TLS Overview** page.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls)
2. Choose an encryption mode.

To adjust your encryption mode with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `ssl` as the setting name in the URI path, and the `value` parameter set to your desired setting (`off`, `flexible`, `full`, `strict`, or `origin_pull`).

## Limitations

Depending on your origin configuration, you may have to adjust settings to avoid [Mixed Content errors](https://developers.cloudflare.com/ssl/troubleshooting/mixed-content-errors/) or [redirect loops](https://developers.cloudflare.com/ssl/troubleshooting/too-many-redirects/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/ssl-modes/","name":"Encryption modes"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/origin-configuration/ssl-modes/full-strict/","name":"Full (strict)"}}]}
```

---

---
title: Off (no encryption)
description: No encryption is used for traffic between browsers and Cloudflare or between Cloudflare and origins. Everything is cleartext HTTP.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Off (no encryption)

Setting your encryption mode to **Off (not recommended)** redirects any HTTPS request to plaintext HTTP.

    flowchart LR
        accTitle: No SSL/TLS Encryption
        accDescr: With an encryption mode of Off, your application does not encrypt traffic between the visitor and Cloudflare or between Cloudflare and your server.
        A[Browser] <--Unencrypted--> B((Cloudflare))<--Unencrypted--> C[(Origin server)]

## Use when

Cloudflare does not recommend setting your encryption mode to **Off**.

## Required setup

* [ Dashboard ](#tab-panel-10509)
* [ API ](#tab-panel-10510)

To change your encryption mode in the dashboard:

1. In the Cloudflare dashboard, go to the **SSL/TLS Overview** page.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls)
2. Choose an encryption mode.

To adjust your encryption mode with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `ssl` as the setting name in the URI path, and the `value` parameter set to your desired setting (`off`, `flexible`, `full`, `strict`, or `origin_pull`).

## Limitations

When you set your encryption mode to **Off**, your application:

* Leaves your visitors and your application [vulnerable to attacks ↗](https://www.cloudflare.com/learning/ssl/why-use-https/).
* Will be marked as "not secure" by Chrome and other browsers, reducing visitor trust.
* Will be penalized in [SEO rankings ↗](https://webmasters.googleblog.com/2014/08/https-as-ranking-signal.html).

### Incompatible settings

When you set your SSL/TLS encryption mode to **Off**, you will not see the options for [**Always Use HTTPS**](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/) or [**Onion Routing**](https://developers.cloudflare.com/network/onion-routing/).

[Authenticated Origin Pull](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/) does not work when your [**SSL/TLS encryption mode**](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/) is set to **Off** or **Flexible**.

  

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/ssl-modes/","name":"Encryption modes"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/origin-configuration/ssl-modes/off/","name":"Off (no encryption)"}}]}
```

---

---
title: Strict (SSL-Only Origin Pull)
description: Regardless of whether the browser-to-Cloudflare connection uses HTTP or HTTPS, Cloudflare always connects to the origin over HTTPS with certificate validation.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Strict (SSL-Only Origin Pull)

Note

This method is only available for Enterprise zones.

When you set your encryption mode to **Strict (SSL-Only Origin Pull)**, connections to the origin will always be made using SSL/TLS, regardless of the scheme requested by the visitor.

The certificate presented by the origin will be validated the same as with [Full (strict) mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/).

## Use when

You want the most secure configuration available for your origin, you are an Enterprise customer, and you meet the requirements for [**Full (strict)** mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/).

## Required setup

The setup is generally the same as [**Full (strict)** mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/), but you select **Strict (SSL-Only Origin Pull)** for your encryption mode.

Note

In addition to **Strict (SSL-Only Origin Pull)** encryption, you can also set up [Authenticated Origin Pulls](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/) to ensure all requests to your origin are evaluated before receiving a response.

### Process

* [ Dashboard ](#tab-panel-10511)
* [ API ](#tab-panel-10512)

To change your encryption mode in the dashboard:

1. In the Cloudflare dashboard, go to the **SSL/TLS Overview** page.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls)
2. Choose an encryption mode.

To adjust your encryption mode with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/) request with `ssl` as the setting name in the URI path, and the `value` parameter set to your desired setting (`off`, `flexible`, `full`, `strict`, or `origin_pull`).

## Limitations

Depending on your origin configuration, you may have to adjust settings to avoid [Mixed Content errors](https://developers.cloudflare.com/ssl/troubleshooting/mixed-content-errors/) or [redirect loops](https://developers.cloudflare.com/ssl/troubleshooting/too-many-redirects/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/ssl-modes/","name":"Encryption modes"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/origin-configuration/ssl-modes/ssl-only-origin-pull/","name":"Strict (SSL-Only Origin Pull)"}}]}
```

---

---
title: SSL/TLS Recommender
description: Get recommendations for the optimal SSL/TLS encryption mode.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# SSL/TLS Recommender

The SSL/TLS Recommender helps you choose which [Encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/) is best for your application.

Warning

Cloudflare is deprecating our SSL/TLS Recommender in favor of [Automatic SSL/TLS](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/#automatic-ssltls-default).

## Availability

| Free         | Pro | Business | Enterprise |     |
| ------------ | --- | -------- | ---------- | --- |
| Availability | Yes | Yes      | Yes        | Yes |

## Common tasks

### Enable SSL/TLS recommendations

To make sure you do not inadvertently block the **SSL/TLS Recommender**, review your settings to make sure your domain:

* Is accessible.
* Is not blocking requests from our bot (which uses a user agent of `Cloudflare-SSLDetector`).
* Does not have any active, SSL-specific [Page Rules](https://developers.cloudflare.com/rules/page-rules/) or [Configuration rules](https://developers.cloudflare.com/rules/configuration-rules/).

Then, you can enable the SSL/TLS recommender.

* [ Dashboard ](#tab-panel-10513)
* [ API ](#tab-panel-10514)

To enable SSL/TLS recommendations in the dashboard:

1. In the Cloudflare dashboard, go to the **SSL/TLS Overview** page.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls)
2. For **SSL/TLS Recommender**, switch the toggle to **On**.

To adjust your SSL/TLS Recommender enrollment with the API, send a [PATCH](https://developers.cloudflare.com/api/resources/ssl/subresources/recommendations/methods/get/) request with the `enabled` parameter set to your desired setting (`true` or `false`).

### Manually trigger a new scan

Once you enable it, the recommender runs future scans periodically — typically every two days — and sends notifications if new recommendations become available.

To manually re-trigger a new scan, disable and then [re-enable SSL/TLS recommendations](#enable-ssltls-recommendations).

## How it works

Once enabled, the SSL/TLS Recommender runs an origin scan using the user agent `Cloudflare-SSLDetector` and ignores your `robots.txt` file (except for rules explicitly targeting the user agent).

Based on this initial scan, the Recommender may decide that you could use a stronger [SSL encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/). It will never recommend a weaker option than what is currently configured.

If so, it will send the application owner an email with the recommended option and add a _Recommended by Cloudflare_ tag to that option on the **SSL/TLS** page. You are not required to use this recommendation.

If you do not receive an email, keep your current **SSL encryption mode**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/origin-configuration/","name":"Origin server"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/origin-configuration/ssl-tls-recommender/","name":"SSL/TLS Recommender"}}]}
```

---

---
title: Features and plans
description: Review information on all Cloudflare SSL/TLS features and their availability.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Features and plans

Cloudflare provides the following features for different [plans ↗](https://www.cloudflare.com/plans/).

## Features

### Advanced Certificates

**Link:**[Advanced Certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)

**Feature availability**
* **Free:** Paid add-on
* **Pro:** Paid add-on
* **Business:** Paid add-on
* **Enterprise:** Paid add-on

### Authenticated origin pull

**Link:**[Authenticated origin pull](https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### Backup Certificates

**Link:**[Backup Certificates](https://developers.cloudflare.com/ssl/edge-certificates/backup-certificates/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Can opt out?**

Enterprise-only

* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

### Custom Certificates

**Link:**[Custom Certificates](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/)

**Feature availability**
* **Free:** No
* **Pro:** No
* **Business:** Yes
* **Enterprise:** Yes

**Certificates included**
* **Free:** 0
* **Pro:** 0
* **Business:** 1 Modern and 1 Legacy
* **Enterprise:** 1 Modern (can purchase more) and 1 Legacy (can purchase more)

### Always Use HTTPS

**Link:**[Always Use HTTPS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### Automatic HTTPS Rewrites

**Link:**[Automatic HTTPS Rewrites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/automatic-https-rewrites/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### Certificate Transparency Monitoring

**Link:**[Certificate Transparency Monitoring](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/certificate-transparency-monitoring/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Email Recipients**
* **Free:** All account members
* **Pro:** All account members
* **Business:** Specified email addresses
* **Enterprise:** Specified email addresses

### Opportunistic Encryption

**Link:**[Opportunistic Encryption](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/opportunistic-encryption/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### HTTP Strict Transport Security

**Link:**[HTTP Strict Transport Security](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/http-strict-transport-security/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### TLS 1.3

**Link:**[TLS 1.3](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/tls-13/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### Minimum TLS Version

**Link:**[Minimum TLS Version](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/minimum-tls/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Per-hostname**
* **Free:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)
* **Pro:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)
* **Business:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)
* **Enterprise:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)

### Certificate Signing Requests

**Link:**[Certificate Signing Requests](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/certificate-signing-requests/)

**Feature availability**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)

### Custom Hostnames

**Link:**[Custom Hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/plans/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Contact your account team

**Hostnames included**

Varies

* **Free:** 100
* **Pro:** 100
* **Business:** 100
* **Enterprise:** Custom

**Max hostnames**
* **Free:** 50,000
* **Pro:** 50,000
* **Business:** 50,000
* **Enterprise:** Unlimited, but contact sales if using over 50,000.

**Price per additional hostname**
* **Free:** $0.10
* **Pro:** $0.10
* **Business:** $0.10
* **Enterprise:** Custom pricing

**[Custom analytics](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/hostname-analytics/)**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**[Custom origin](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/)**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**[SNI Rewrite for Custom Origin](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/#sni-rewrites)**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Contact your account team

**[Custom certificates](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/)**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

**[CSR support](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/certificate-signing-requests/)**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

**[Selectable CA](https://developers.cloudflare.com/ssl/reference/certificate-authorities/)**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

**Wildcard custom hostnames**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

**Non-SNI support for SaaS zone**
* **Free:** No
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**[mTLS support](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/)**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

**[WAF for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/waf-for-saas/)**
* **Free:** WAF rules with current zone plan
* **Pro:** WAF rules with current zone plan
* **Business:** WAF rules with current zone plan
* **Enterprise:** Create and apply custom firewall rulesets.

**[Apex proxying/BYOIP](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/)**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Paid add-on

**[Custom metadata](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/)**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Paid add-on

### Custom origin trust store

**Link:**[Custom origin trust store](https://developers.cloudflare.com/ssl/origin-configuration/custom-origin-trust-store/)

**Feature availability**
* **Free:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)
* **Pro:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)
* **Business:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)
* **Enterprise:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)

### SSL/TLS encryption mode

**Link:**[SSL/TLS encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Strict (SSL-Only Origin Pull)**

Enterprise-only

* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

### Keyless SSL

**Link:**[Keyless SSL](https://developers.cloudflare.com/ssl/keyless-ssl/)

**Feature availability**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Paid add-on

### Origin certificates

**Link:**[Origin certificates](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### Staging environment

**Link:**[Staging environment](https://developers.cloudflare.com/ssl/edge-certificates/staging-environment/)

**Feature availability**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes (open beta)

### SSL/TLS Recommender

**Link:**[SSL/TLS Recommender](https://developers.cloudflare.com/ssl/origin-configuration/ssl-tls-recommender/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### Custom cipher suites

**Link:**[Custom cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/)

**Feature availability**
* **Free:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)
* **Pro:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)
* **Business:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)
* **Enterprise:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)

### Total TLS

**Link:**[Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/)

**Feature availability**
* **Free:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)
* **Pro:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)
* **Business:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)
* **Enterprise:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)

### Delegated DCV

**Link:**[Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/)

**Feature availability**
* **Free:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)
* **Pro:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)
* **Business:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)
* **Enterprise:** Included with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)

### Universal Certificates

**Link:**[Universal Certificates](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

### Client Certificates

**Link:**[Client Certificates](https://developers.cloudflare.com/ssl/client-certificates/)

**Feature availability**
* **Free:** Yes
* **Pro:** Yes
* **Business:** Yes
* **Enterprise:** Yes

**Client Certificates included, issued by a Cloudflare Managed CA**
* **Free:** 100
* **Pro:** 100
* **Business:** 100
* **Enterprise:** 100 (default), but can allocate more quota.

**[Bring your own CA](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/)**
* **Free:** No
* **Pro:** No
* **Business:** No
* **Enterprise:** Yes

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/all-features/","name":"Features and plans"}}]}
```

---

---
title: Browser compatibility
description: Review information about browser compatibility for the different Cloudflare SSL/TLS offerings.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Browser compatibility

Cloudflare attempts to provide compatibility for as wide a range of user agents (browsers, API clients, etc.) as possible. However, the specific set of supported clients can vary depending on the different SSL/TLS certificate types, your visitor's [browser version](#non-sni-support), and the [certificate authority (CA)](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) that issues the certificate.

## Universal SSL

Cloudflare Universal SSL only supports browsers and API clients that use the [Server Name Indication (SNI) ↗](https://www.cloudflare.com/learning/ssl/what-is-sni/) extension to the TLS protocol.

Also, for zones on Free plan, Universal SSL is only compatible with browsers that support Elliptic Curve Digital Signature Algorithm (ECDSA).

Paid plans have additional compatibility, also supporting RSA algorithm.

## Other certificate types

Refer to [Certificate authorities](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) for a detailed list of Cloudflare SSL/TLS offerings, the different algorithms available, and browser compatibility for each CA.

## Non-SNI support

Although [SNI extensions ↗](https://www.cloudflare.com/learning/ssl/what-is-sni/) to the TLS protocol were standardized in 2003, some browsers and operating systems only implemented this extension when TLS 1.1 was released in 2006 (or 2011 for mobile browsers). If your visitors use devices that have not been updated since 2011, they may not have SNI support.

To support non-SNI requests, you can:

* [Upload a custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/#upload-a-custom-certificate) and specify a value of `Legacy` for its client support.  
Note that `Legacy` custom certificates are not compatible with [BYOIP](https://developers.cloudflare.com/byoip/) and that, unlike [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) or [advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/), Cloudflare does not manage issuance and renewal for [custom certificates](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/).
* (BYOIP customers only) Enterprise customers can choose to bring their own IP prefix to the Cloudflare network and [specify the default SNI used for any non-SNI handshake in the address map](https://developers.cloudflare.com/byoip/address-maps/setup/#non-sni-support).
* (Paid plans only) [Contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) and request a set of non-SNI IPs for your zone.

## HTTPS records

[HTTPS Service (HTTPS) records](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#svcb-and-https) allow you to provide a client with information about how it should connect to a server upfront, without the need of an initial plaintext HTTP connection.

If your domain has [HTTP/2 or HTTP/3 enabled](https://developers.cloudflare.com/speed/optimization/protocol/), [proxied DNS records](https://developers.cloudflare.com/dns/proxy-status/), and is also using [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/), Cloudflare automatically generates HTTPS records on the fly, to advertise to clients how they should connect to your server.

Universal SSL required for automatic HTTPS records

Disabling Universal SSL will prevent automatic HTTPS record generation for proxied hostnames, even if you have [Advanced Certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) or [custom certificates](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) configured. This is because automatic HTTPS record generation is tied specifically to the Universal SSL feature.

If you need HTTPS records without Universal SSL, you can manually add them, but only if **all records with the same name are DNS-only (grey cloud)**. Refer to [SVCB and HTTPS records](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#svcb-and-https) for details and examples.

## OCSP and HTTP versions

Cloudflare's OCSP implementation uses HTTP/1.1 by default for plain HTTP connections.

For HTTPS connections, the client automatically attempts to use HTTP/2 if the server supports it through the TLS ALPN (Application-Layer Protocol Negotiation) extension. If HTTP/2 is not available or supported by the server, it will fall back to HTTP/1.1.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/browser-compatibility/","name":"Browser compatibility"}}]}
```

---

---
title: Certificate and hostname priority
description: Learn about how Cloudflare decides which certificate and associated SSL/TLS settings to apply to individual hostnames.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Certificate and hostname priority

When a new certificate is created, Cloudflare first deploys the certificate and then serves it.

---

## Certificate deployment

For any given hostname, Cloudflare uses the following order to determine which certificate (and associated TLS settings) to apply to that hostname:

1. **Hostname specificity**: A specific subdomain certificate (`www.example.com`) would take precedence over a wildcard certificate (`*.example.com`) for requests to `www.example.com`.
2. **Zone specificity**: A specific subdomain certificate (`www.example.com`) would take precedence over a custom hostname certificate if the domain is active as a zone on Cloudflare.
3. **Certificate priority**: If the hostname is the same, certain types of certificates take precedence over others.  
| Priority | Certificate Type                                                                                                         |  
| -------- | ------------------------------------------------------------------------------------------------------------------------ |  
| 1        | [Keyless SSL](https://developers.cloudflare.com/ssl/keyless-ssl/)                                                        |  
| 2        | [Custom Legacy](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/)                            |  
| 3        | [Custom Modern](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/)                            |  
| 4        | [Custom Hostname (Cloudflare for SaaS)](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) |  
| 5        | [Advanced](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)                        |  
| 6        | [Advanced - Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/)            |  
| 7        | [Universal](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/)                                      |
4. **Certificate expiration**: The most recently ordered certificate takes precedence unless a certificate deletion has occurred. If and when a certificate is deleted, the certificate with the latest expiration date is deployed.

Note

In this case, when the certificate with the closest expiration date is renewed, it will then become the one with the latest expiration date and get presented.

---

## Certificate presentation

Cloudflare uses the following order to determine the certificate and settings used during a TLS handshake:

1. **SNI match**: Certificates and settings that match the SNI hostname _exactly_ take precedence.
2. **SNI wildcard match**: If there is not an exact match between the hostname and SNI hostname, Cloudflare uses certificates and settings that match an SNI wildcard.
3. **IP address**: If no SNI is presented, Cloudflare uses certificate based on the IP address (the hostname can support TLS handshakes made without SNI).

---

## Hostname priority

When multiple proxied DNS records exist for a hostname, in multiple zones — usually due to [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) — only one record will control the zone settings and associated origin server.

Cloudflare determines this priority in the following order, assuming each record exists and is proxied (orange-clouded):

1. **Exact hostname match**:  
   1. [New custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/) (belonging to a SaaS provider)  
   2. [Legacy custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/reference/versioning/) (belonging to a SaaS provider)  
   3. [DNS](https://developers.cloudflare.com/dns/proxy-status/) (belonging to the logical DNS zone)
2. **Wildcard hostname match**:  
   1. DNS (belonging to the logical DNS zone)  
   2. New custom hostname (belonging to a SaaS provider)

If a hostname resource record is not proxied (gray-clouded) for a zone on Cloudflare, that zone's settings are not applied and any settings configured at the associated origin are applied instead. This origin could be another zone on Cloudflare or any other server.

### Example scenarios

#### Scenario 1

Customer1 uses Cloudflare as authoritative DNS for the zone `shop.example.com`. Customer2 is a SaaS provider that creates and successfully [verifies the new custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/) `shop.example.com`. Afterward, traffic starts routing over Customer2's zone:

* If Customer1 wants to regain control of their zone, Customer1 contacts Customer2 and requests them to delete the custom hostname record. Customer1 should make sure to have their record target updated to something other than the SaaS provider target, otherwise Customer1 would get a [1014 error](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-1xxx-errors/error-1014/).
* If Customer1 already has a proxied record for `www.example.com` when Customer2 creates and verifies a new custom hostname `www.example.com`, [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/) applies.
* If Customer1 already has a proxied record for `www.example.com` in a legacy custom hostname setup (with another SaaS provider, Customer3) and Customer2 creates and verifies a new wildcard custom hostname for `*.example.com`, legacy custom hostname on Customer3 platform takes precedence due to exact hostname match.

#### Scenario 2

A customer has a [proxied](https://developers.cloudflare.com/dns/proxy-status/) DNS record for their domain. The customer's zone on Cloudflare is using a Free plan.

This customer is also using a SaaS provider that uses Cloudflare for SaaS. The SaaS provider is using a Cloudflare Enterprise plan.

If the provider is using a wildcard custom hostname, then the original customer's plan limits will take precedence over the provider's plan limits (Cloudflare will treat the zone as a Free zone). To apply the Enterprise limits through Cloudflare for SaaS, the original customer's zone would need to either use a [DNS-only](https://developers.cloudflare.com/dns/proxy-status/) record or the SaaS provider would need to use an exact hostname match.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/certificate-and-hostname-priority/","name":"Certificate and hostname priority"}}]}
```

---

---
title: Certificate authorities
description: For publicly trusted certificates, Cloudflare partners with different certificate authorities (CAs). Refer to this page to check what CAs are used for each Cloudflare offering and for more details about the CAs features, limitations, and browser compatibility.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Certificate authorities

For publicly trusted certificates, Cloudflare partners with different certificate authorities (CAs). Refer to this page to check what CAs are used for each Cloudflare offering and for more details about the CAs [features, limitations, and browser compatibility](#features-limitations-and-browser-compatibility).

## Availability per certificate type and encryption algorithm

| Certificate                                                                                                                                        | Algorithm                 | [Let's Encrypt](#lets-encrypt) | [Google Trust Services](#google-trust-services) | [SSL.com](#sslcom) | [Sectigo](#sectigo) |
| -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | ------------------------------ | ----------------------------------------------- | ------------------ | ------------------- |
| [Universal](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/)                                                                | ECDSARSA(Paid plans only) | ✅✅                             | ✅✅                                              | ✅✅                 | N/AN/A              |
| [Advanced](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)                                                  | ECDSARSA                  | ✅✅                             | ✅✅                                              | ✅  ✅               | N/AN/A              |
| [Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/)                                                 | ECDSARSA                  | ✅✅                             | ✅✅                                              | ✅  ✅               | N/AN/A              |
| [SSL for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/) | ECDSARSA                  | ✅✅                             | ✅✅                                              | ✅  ✅               | N/AN/A              |
| [Backup](https://developers.cloudflare.com/ssl/edge-certificates/backup-certificates/)                                                             | ECDSARSA                  | ✅✅                             | ✅✅                                              | ✅✅                 | ✅✅                  |

## Features, limitations, and browser compatibility

Universal SSL

For Universal certificates, Cloudflare controls the validity periods and certificate authorities (CAs), making sure that renewal always occur. For details, refer to [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/).

---

### Let's Encrypt

* Supports [validity periods](https://developers.cloudflare.com/ssl/reference/certificate-validity-periods/) of 90 days.
* [DCV tokens](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/) are valid for 7 days.

#### Limitations

* Hostname on certificate can contain up to 10 levels of subdomains.
* Duplicate certificate limit of [5 certificates ↗](https://letsencrypt.org/docs/rate-limits/) per week.
* Redsys[1](#user-content-fn-1) is not compatible with Let's Encrypt certificates. If you use Redsys and find issues with Let's Encrypt certificates, order an advanced certificate or upload a custom certificate to use a different CA.

#### Browser compatibility

Warning

This section summarizes commonly requested client support information. For the complete and most up-to-date certificate compatibility, refer to [Let's Encrypt documentation ↗](https://letsencrypt.org/docs/certificate-compatibility/).

The main determining factor for whether a platform can validate Let's Encrypt certificates is whether that platform trusts the self-signed ISRG Root X1 certificate. As Let's Encrypt announced a [change in its chain of trust in 2024 ↗](https://blog.cloudflare.com/shortening-lets-encrypt-change-of-trust-no-impact-to-cloudflare-customers/), older devices (for example Android 7.0 and earlier) that only trust the cross-signed version of the ISRG Root X1 are no longer compatible.

You can find the full list of supported clients in the [Let's Encrypt documentation ↗](https://letsencrypt.org/docs/certificate-compatibility/). Older versions of Android and Java clients might not be compatible with Let's Encrypt certificates.

#### Other resources

[Let's Encrypt Root CAs ↗](https://letsencrypt.org/certificates/): For checking compatibility between chain and client. As explained in [Certificate pinning](https://developers.cloudflare.com/ssl/reference/certificate-pinning/), you should **not** use this list for pinning against.

---

### Google Trust Services

* Supports [validity periods](https://developers.cloudflare.com/ssl/reference/certificate-validity-periods/) of 14, 30, and 90 days.
* [DCV tokens](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/) are valid for 14 days.

#### Browser compatibility (most compatible)

Warning

This section summarizes commonly requested client support information. For the complete and most up-to-date certificate compatibility, refer to [Google Trust Services documentation ↗](https://pki.goog/faq/).

By cross-signing with a [GlobalSign root CA ↗](https://valid.r1.roots.globalsign.com/) that has been installed in client devices for more than 20 years, Google Trust Services can ensure optimal support across a wide range of devices.

Currently trusted by Microsoft, Mozilla, Safari, Cisco, Oracle Java, and Qihoo’s 360 browser, all browsers or operating systems that depend on these root programs are covered.

You can use the [root CAs list ↗](https://pki.goog/faq/#connecting-to-google) for checking compatibility between chain and client but, as explained in [Certificate pinning](https://developers.cloudflare.com/ssl/reference/certificate-pinning/), you should **not** use this list for pinning against.

---

### SSL.com

* Supports [validity periods](https://developers.cloudflare.com/ssl/reference/certificate-validity-periods/) of 14, 30, and 90 days. Enterprise customers using [advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) can also choose a validity period of one year.
* [DCV tokens](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/) are valid for 14 days.

#### Limitations

SSL.com DCV tokens are specific for RSA certificates and ECDSA certificates. This means that, for cases where you have to [manually perform DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/#partial-dns-setup---action-sometimes-required), you will have to place two validation tokens per certificate order. To avoid management overhead, consider using a [full setup](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/#full-dns-setup---no-action-required), or setting up [Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/).

#### Browser compatibility

Warning

This section summarizes commonly requested client support information. For the complete and most up-to-date certificate compatibility, refer to [SSL.com documentation ↗](https://www.ssl.com/browser%5Fcompatibility/).

SSL.com is highly compatible, being accepted by over 99.9% of browsers, tablets, and mobile devices.

SSL.com certificates are [cross-signed with Certum ↗](https://www.ssl.com/repository/) and the [CA that cross-signs intermediates ↗](https://crt.sh/?caid=840) is from 2004.

#### Other resources

[Acceptable top level domains (TLDs) and current restrictions ↗](https://www.ssl.com/acceptable-top-level-domains-tlds-for-ssl-certificates/)

---

### Sectigo

* Only used for [Backup certificates](https://developers.cloudflare.com/ssl/edge-certificates/backup-certificates/).
* Backup certificates are valid for 90 days.

#### Browser compatibility

Refer to [Sectigo documentation ↗](https://www.sectigo.com/resource-library/sectigo-certificate-authority-root-keys).

---

## CAA records

A Certificate Authority Authorization (CAA) DNS record specifies which certificate authorities (CAs) are allowed to issue certificates for a domain. This record reduces the chance of unauthorized certificate issuance and promotes standardization across your organization.

  
If you are using Cloudflare as your DNS provider, then the CAA records will be added on your behalf. If you need to add CAA records, refer to [Add CAA records](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/).

The following table lists the CAA record content for each CA:

| Certificate authority | CAA record content                 |
| --------------------- | ---------------------------------- |
| Let's Encrypt         | letsencrypt.org                    |
| Google Trust Services | pki.goog; cansignhttpexchanges=yes |
| SSL.com               | ssl.com                            |
| Sectigo               | sectigo.com                        |

## Footnotes

1. A payment gateway used with some ecommerce plugins. [↩](#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":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/certificate-authorities/","name":"Certificate authorities"}}]}
```

---

---
title: Certificate pinning
description: Learn why Cloudflare does not support HTTP public key pinning (HPKP) and consider an alternative solution to prevent certificate misissuance.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Certificate pinning

Cloudflare does not support [HTTP public key pinning (HPKP)](https://developers.cloudflare.com/ssl/reference/certificate-pinning/) for universal, advanced, or custom hostname certificates.

Cloudflare regularly rotates the edge certificates provisioned for your domain. If HPKP was enabled, your domain would go offline each time a certificate rotates because the new certificate would not match the pinned key. Additionally, [industry experts ↗](https://scotthelme.co.uk/im-giving-up-on-hpkp/) discourage using HPKP. For a detailed overview, refer to the Cloudflare blog post on [why certificate pinning is outdated ↗](https://blog.cloudflare.com/why-certificate-pinning-is-outdated/).

## Recommended alternative

The problem HPKP tries to solve is preventing certificate misissuance. A safer way to detect misissuance without risking downtime is [Certificate Transparency Monitoring](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/certificate-transparency-monitoring/), which alerts you when a certificate is issued for your domain.

## If you must pin certificates

If your use case requires certificate pinning, the only advisable approach is to upload a [custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) to Cloudflare and pin to that certificate. Because you control the certificate lifecycle — including renewal timing, CA selection, and key material — you can ensure pin continuity. However, pinning still carries outage risk: if a renewal deploys a new key, clients pinned to the old key will fail TLS. If you need pin continuity, you must intentionally reuse the same key material during renewal. Test renewed certificates in the [staging environment](https://developers.cloudflare.com/ssl/edge-certificates/staging-environment/) before production.

Select the [**user-defined** bundle method](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/bundling-methodologies/#user-defined) so that you control exactly which CA, intermediate, and leaf certificate are served.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/certificate-pinning/","name":"Certificate pinning"}}]}
```

---

---
title: Rotate ACM certificate packs
description: Replace an Advanced Certificate Manager certificate pack with zero downtime by creating the new pack, waiting for it to go Active, then deleting the old one.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Rotate ACM certificate packs

Advanced Certificate Manager (ACM) certificate packs cannot be updated in place. To replace an existing pack - for example, to change the certificate authority, add hostnames, or change validation method - you create a new pack, wait for it to reach **Active** status, and then delete the old one.

The key principle is to ensure the new certificate pack reaches **Active** before removing the old one. This avoids any gap in coverage and means there is no downtime for your users.

---

## Recommended rotation process

### 1\. Create the new certificate pack

* [ Dashboard ](#tab-panel-10515)
* [ API ](#tab-panel-10516)
* [ Terraform ](#tab-panel-10517)

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. Select **Order Advanced Certificate**.
3. Configure the new certificate pack with the desired hostnames, certificate authority, and validation method.
4. Select **Save**.

Use the [Order Certificate Pack](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/create/) endpoint to create the new pack.

Add a new `cloudflare_certificate_pack` resource to your Terraform configuration and apply it. Refer to the [Terraform-specific notes](#terraform) below before proceeding.

### 2\. Wait for Active status

After ordering, the new certificate pack moves through several intermediate states before it is ready to serve traffic:

1. **Initializing**
2. **Pending Validation**
3. **Pending Issuance**
4. **Pending Deployment**
5. **Active**

Do not delete the old certificate pack until the new one reaches **Active**. Refer to [Certificate statuses](https://developers.cloudflare.com/ssl/reference/certificate-statuses/) for a description of each stage.

Monitor progress on the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page in the dashboard, or poll the [Get Certificate Pack](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/get/) API endpoint.

For zones using Cloudflare as authoritative DNS (full setup), most validations complete within minutes. For [partial (CNAME) setups](https://developers.cloudflare.com/dns/zone-setups/partial-setup/), you will need to place DCV tokens manually - refer to [DCV methods](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/) for details. DCV tokens expire if not satisfied within their validity window (7 days for Let's Encrypt, 14 days for Google Trust Services and SSL.com).

### 3\. Delete the old certificate pack

Once the new pack is **Active**, it is safe to delete the old one.

* [ Dashboard ](#tab-panel-10518)
* [ API ](#tab-panel-10519)
* [ Terraform ](#tab-panel-10520)

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. Select the old certificate pack.
3. Select **Delete Certificate**.

Use the [Delete Certificate Pack](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/delete/) endpoint.

Remove the old `cloudflare_certificate_pack` resource from your Terraform configuration and apply. Refer to the [Terraform-specific notes](#terraform) below.

### 4\. Expect a brief Pending Deployment state

After the old pack is deleted, the remaining certificate may briefly show **Pending Deployment** before returning to **Active**. This reflects a normal edge re-evaluation cycle as the global network reconciles the change, and typically resolves within a few minutes with no traffic impact.

If the certificate remains in **Pending Deployment** for longer than expected, refer to [Certificate statuses](https://developers.cloudflare.com/ssl/reference/certificate-statuses/) and contact [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/).

---

## Terraform

Certificate packs cannot be updated in place - every attribute of the `cloudflare_certificate_pack` resource forces a new resource on change. Plan your rotation around this constraint.

Warning

Importing existing certificate packs into Terraform state is supported but not recommended. If Cloudflare reissues the certificate (for example, on renewal), the resource ID changes and your Terraform state goes out of sync. The recommended pattern is to manage the full lifecycle through Terraform - create, wait for active, then delete - rather than importing existing packs.

### Wait for Active automatically

Set `wait_for_active_status = true` on the new resource to have Terraform block the apply until the certificate pack reaches **Active**. This removes the need to manually poll the dashboard or API between steps 1 and 3.

### Recommended pattern

1. Add the new `cloudflare_certificate_pack` resource with `wait_for_active_status = true` and run `terraform apply`. The apply will not complete until the pack is Active.
2. Remove the old resource from your configuration and run `terraform apply` to delete it.

For zero-downtime rotation of a single resource (where you cannot have both old and new in state simultaneously), use Terraform's [create\_before\_destroy ↗](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#create%5Fbefore%5Fdestroy) lifecycle meta-argument.

Refer to the [cloudflare\_certificate\_pack provider documentation ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/certificate%5Fpack) for the full resource schema.

---

## Common rotation issues

### Let's Encrypt rate limit

Let's Encrypt limits new certificates to five per seven-day window for the same exact set of hostnames. Repeated rotations (for example, during testing or automation loops) can exhaust this limit and block further issuance for up to a week.

If you hit this limit, switch the certificate authority to [Google Trust Services or SSL.com](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) or wait for the rate limit window to expire. Refer to [Let's Encrypt rate limits ↗](https://letsencrypt.org/docs/rate-limits/) for details.

### Pack stuck in Pending Validation

If a new pack remains in **Pending Validation** for more than 15 minutes, check that your DCV method is set up correctly. Refer to [Domain Control Validation](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/) and [Troubleshoot domain control validation](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/troubleshooting/).

---

## Distinction from custom certificate replacement

This page covers **ACM certificate packs** (Cloudflare-managed Domain Validated certificates ordered via Advanced Certificate Manager).

If you are using a **custom certificate** (a certificate you supplied), Cloudflare provides an in-place **Replace SSL certificate and key** flow that handles the rotation without requiring you to manage two packs. Refer to [Manage custom certificates](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/uploading/#update-an-existing-custom-certificate).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/certificate-rotation/","name":"Rotate ACM certificate packs"}}]}
```

---

---
title: Certificate statuses
description: Understand certificate statuses in Cloudflare SSL/TLS, including stages like Initializing, Pending Validation, and Active. Monitor via dashboard or command line.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Certificate statuses

Certificates statuses show which stage of the issuance process each certificate is in.

## New certificates

When you order a new certificate, either an [edge certificate](https://developers.cloudflare.com/ssl/edge-certificates/) or a certificate used for a [custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/), its status will move through various stages as it progresses to Cloudflare's global network:

1. Initializing
2. Pending Validation
3. Pending Issuance
4. Pending Deployment
5. Active

Once you issue a certificate, it should be in **Pending Validation**, but change to **Active** after the validation is completed. If you see any errors, you or your customer may need to take additional actions to validate the certificate.

If you deactivate a certificate, it will become a **Deactivating** and then an **Inactive** status.

### Certificate replacement

When replacing a certificate, you may note a **Pending Cleanup** status. Old certificates are not deleted until the replacement has been successfully issued. This ensures TLS will not break for the hostname while the certificate is being replaced.

When the new certificate is successfully issued and activated, the status for the old certificate will transition from **Pending Cleanup**, and the certificate will be deleted.

## Custom certificates

If you are using a [custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) and your [zone status](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/) is **Pending** or **Moved**, your certificate may have a status of **Holding Deployment**.

When your zone becomes active, your custom certificate will deploy automatically (also moving to an **Active** status).

If your zone is already active when you upload a custom certificate, you will not see this status.

## Staging certificates

When you create certificates in your [staging environment](https://developers.cloudflare.com/ssl/edge-certificates/staging-environment/), those staging certificates have their own set of statuses:

* **Staging deployment**: Similar to **Pending Deployment**, but for staging certificates.
* **Staging active**: Similar to **Active**, but for staging certificates.
* **Deactivating**: Your staging certificate is in the process of becoming **Inactive**.
* **Inactive**: Your staging certificate is not at the edge, but you can deploy it if needed.

## Client certificates

When you use [client certificates](https://developers.cloudflare.com/ssl/client-certificates/), those client certificates have their own set of statuses:

* **Active**: The client certificate is active.
* **Revoked**: The client certificate is revoked.
* **Pending Reactivation**: The client certificate was revoked, but it is being restored.
* **Pending Revocation**: The client certificate was active, but it is being revoked.

---

## Monitor certificate statuses

### SSL/TLS

Monitor a certificate's status on the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page or by using the [Get Certificate Pack endpoint](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/get/).

For more details on certificate validation, refer to [Domain Control Validation](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/).

### SSL for SaaS

Monitor a certificate's status on the [**Custom Hostnames** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames) page or by using the [Custom Hostname Details endpoint](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/get/).

The Custom Hostname Details endpoint returns separate status fields for hostname activation and certificate status. Use the top-level `status` field to monitor hostname activation. Use the nested `ssl.status` field to monitor certificate issuance and deployment.

For production HTTPS, treat a custom hostname as ready when both status fields are `active` and the customer's DNS points to your Cloudflare for SaaS target.

For more details on certificate validation, refer to [Issue and validate certificates](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/).

### Via the command line

To view certificates, use `openssl` or your browser. The command below can be used in advance of your customer pointing the `app.example.com` hostname to the edge ([provided validation was completed](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/)).

Terminal window

```

openssl s_client -servername app.example.com -connect $CNAME_TARGET:443 </dev/null 2>/dev/null | openssl x509 -noout -text | grep app.example.com


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/certificate-statuses/","name":"Certificate statuses"}}]}
```

---

---
title: Validity periods and renewal
description: Learn about Cloudflare SSL certificate validity periods, auto renewal processes, and the benefits of shorter validity periods for enhanced security.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Validity periods and renewal

For certificates managed by Cloudflare, attempts to renew start at the auto renewal period and continue up until 24 hours before expiration. The auto renewal period varies according to the certificate validity period, as explained in the sections below.

If a certificate fails to renew and another valid certificate exists for the hostname, Cloudflare will deploy the valid certificate within the last 24 hours before expiration.

## Certificate types

### Universal SSL

For Universal certificates, Cloudflare controls the validity periods and certificate authorities (CAs), making sure that renewal always occur.

Partial setup and DCV

If you are on a [CNAME setup (partial)](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/enable-universal-ssl/#partial-dns-setup), make sure [Domain control validation (DCV)](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/) is configured correctly. Refer to [Troubleshooting DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/troubleshooting/) for further help.

Universal certificates have a 90-day validity period. The auto renewal period starts 30 days before expiration.

### Advanced certificates

When you order an [advanced certificate](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/), you can select different certificate validity periods. Each certificate validity period has a corresponding auto renewal period, when [attempts to renew](https://developers.cloudflare.com/ssl/reference/certificate-validity-periods/) will start.

| Certificate validity period | Auto renewal period | Notes                                                                                                                                                                                                                                                |
| --------------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1 year                      | 30 days             | Limited to Enterprise customers using [advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) with [SSL.com](https://developers.cloudflare.com/ssl/reference/certificate-authorities/#sslcom) |
| 3 months                    | 30 days             |                                                                                                                                                                                                                                                      |
| 1 month                     | 7 days              | Not supported by [Let's Encrypt](https://developers.cloudflare.com/ssl/reference/certificate-authorities/#lets-encrypt)                                                                                                                              |
| 2 weeks                     | 3 days              | Not supported by [Let's Encrypt](https://developers.cloudflare.com/ssl/reference/certificate-authorities/#lets-encrypt)                                                                                                                              |

Note

For more details on the `validity_days` parameter used in API calls, refer to [Order Advanced Certificate Pack](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/create/).

### Custom certificates

For information regarding custom certificates (managed by you), consider this other page on [renewal and expiration](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/renewing/).

### SSL for SaaS

For SSL for SaaS certificates, refer to [Renew certificates](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/renew-certificates/).

## Domain control validation (DCV)

Before a certificate authority (CA) will issue a certificate for a domain, the requester must prove they have control over that domain. This process is known as domain control validation (DCV).

[HTTP validation](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/http/) is attempted on renewals but will fall back to TXT validation depending on the certificate validity period:

* 90-days certificates: after failing for 15 days
* 30-days certificates: after failing for 7 days
* 14-days certificates: after failing for 3 days

## Benefits of shorter validity periods

Cloudflare only issues certificates with validity periods of three months or less for two reasons.

First, shorter-lived certificates limit the damage from key compromise and mistaken issuance. Any compromised key material will be valid for a shorter period of time.

Second, shorter certificates encourage automation. The more frequently you have to do a task, the more likely you will want to automate it. Automation also means that you are less likely to let a certificate expire in production or give a person access to key material.

For more details on the benefits of shorter validity periods, refer to our [blog post introducing Advanced Certificate Manager ↗](https://blog.cloudflare.com/advanced-certificate-manager/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/certificate-validity-periods/","name":"Validity periods and renewal"}}]}
```

---

---
title: Cloudflare and CVE-2019-1559
description: How Cloudflare addressed the CVE-2019-1559 TLS vulnerability.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare and CVE-2019-1559

The [GOLDENDOODLE and Zombie POODLE attacks ↗](https://www.tripwire.com/state-of-security/vulnerability-management/zombie-poodle-goldendoodle/) affect applications that use certain cipher suites associated with TLS 1.2.

Any application on Cloudflare, however, is not vulnerable to these attacks because Cloudflare does not use the affected version of openssl at its edge.

Cloudflare could not remove these cipher suites from our edge by default because we did not want to break customer applications using legacy cipher suites.

## Remove warnings from external security scanners

Even though your application is not vulnerable to CVE-2019-1559, some security scanners may flag your application erroneously.

To remove these warnings, refer to [Customize cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/) and exclude the following ciphers:

* `ECDHE-ECDSA-AES256-SHA384`
* `ECDHE-ECDSA-AES128-SHA256`
* `ECDHE-RSA-AES256-SHA384`

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/cloudflare-and-cve-2019-1559/","name":"Cloudflare and CVE-2019-1559"}}]}
```

---

---
title: PCI compliance and vulnerabilities mitigation
description: PCI compliance status and TLS vulnerability mitigations.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# PCI compliance and vulnerabilities mitigation

Both [TLS 1.0 and TLS 1.1](https://developers.cloudflare.com/ssl/reference/protocols/) are insufficient for protecting information due to known vulnerabilities. Specifically for Cloudflare customers, the primary impact of PCI is that TLS 1.0 and TLS 1.1 are insufficient to secure payment card related traffic.

PCI standards recommend using TLS 1.2 or higher. Refer to [Compliance standards](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/compliance-status/) for a list of recommended cipher suites.

Cloudflare also [implements mitigations against known vulnerabilities](#known-vulnerabilities-mitigations) for TLS 1.0 and 1.1.

## Set Minimum TLS Version to 1.2

To configure your Cloudflare domain to only allow connections using TLS 1.2 or newer protocols:

1. In the Cloudflare dashboard, go to the **Edge Certificates** page.  
[ Go to **Edge Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates)
2. For **Minimum TLS Version**, select **TLS 1.2** or higher.

Refer to [Minimum TLS version](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/minimum-tls/) for more information about this setting and other setup options.

## Known vulnerabilities mitigations

There are several mitigations Cloudflare performs against known vulnerabilities for TLS versions prior to 1.2\. For example, Cloudflare does not support:

* Header compression in TLS
* Header compression in SPDY 3.1
* RC4
* SSL 3.0
* Renegotiation with clients
* DHE ciphersuites
* Export-grade ciphers

Cloudflare mitigations protect against several attacks:

* CRIME
* BREACH
* POODLE
* RC4 Cryptographic Weaknesses
* SSL Renegotiation Attack
* Protocol Downgrade Attacks
* FREAK
* LogJam
* 3DES is disabled entirely for TLS 1.1 and 1.2 and Cloudflare implements mitigations for TLS 1.0

Cloudflare provides additional mitigations for:

* Heartbleed
* Lucky Thirteen
* CCS injection vulnerability

Cloudflare has patched all servers against these vulnerabilities. Also, the [Cloudflare Web Application Firewall](https://developers.cloudflare.com/waf/) has managed rules that mitigate several of these vulnerabilities including Heartbleed and ShellShock.

### Return of Bleichenbacher's Oracle Threat (ROBOT)

Security scans that note the presence of ROBOT while on Cloudflare are a false positive. Cloudflare checks padding in real time and swaps to a random session key if the padding is incorrect.

### Sweet32 (CVE-2016-2183)

A vulnerability in the use of the Triple DES (3DES) encryption algorithm in the Transport Layer Security (TLS) protocol. Sweet32 is currently a proof of concept attack, there are no known examples of this in the wild. Cloudflare has manually mitigated the vulnerability for TLS 1.0 in the following manner:

* The attacker must collect 32GB of data from a single TLS session.
* Cloudflare forces new TLS 1.0 session keys on the affected 3DES cipher well before 32GB of data is collected.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/compliance-and-vulnerabilities/","name":"PCI compliance and vulnerabilities mitigation"}}]}
```

---

---
title: DigiCert Legacy Root (G1) distrust by major browsers
description: Learn how the DigiCert G1 root distrust may affect your Cloudflare configuration.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DigiCert Legacy Root (G1) distrust by major browsers

Browsers and operating systems are completing the removal of DigiCert's legacy G1 root certificates from their trust stores, effective **April 15, 2026**.

DigiCert announced this planned deprecation in 2023 and has been issuing certificates from their newer G2 roots since 2020.

Since DigiCert is not within the [certificate authorities](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) used by Cloudflare, this change may only affect customers who upload [custom certificates](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) issued from DigiCert G1 roots.

## The change

The primary root being distrusted is **DigiCert Global Root CA**. The distrust also affects other legacy G1 intermediates cross-signed from this root.

DigiCert Global Root G2 and G3 remain fully trusted. Certificates that chain to G2 are unaffected.

Refer to [DigiCert's root and intermediate CA certificate updates ↗](https://knowledge.digicert.com/general-information/digicert-root-and-intermediate-ca-certificate-updates-2023) for the full list of affected roots.

## DigiCert's recommendation

DigiCert recommends reissuing any affected certificates from a G2 intermediate. This is a standard reissuance — you do not need to generate a new key in most cases.

## Cloudflare-managed certificates

Since Cloudflare does not use DigiCert roots, you can avoid this dependency entirely by switching to Cloudflare-managed certificates:

* Use [Advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) for more control and flexibility with automatic renewals.
* Enable [Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/) to automatically issue certificates for your [proxied hostnames](https://developers.cloudflare.com/dns/proxy-status/).
* Use [Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/) to reduce manual intervention when renewing certificates for [partial (CNAME) setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/) zones.

## More resources

* [DigiCert root and intermediate CA certificate updates ↗](https://knowledge.digicert.com/general-information/digicert-root-and-intermediate-ca-certificate-updates-2023)
* [Custom certificates](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/)
* [Certificate bundling methodologies](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/bundling-methodologies/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/migration-guides/","name":"Migration guides"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/reference/migration-guides/digicert-g1-distrust/","name":"DigiCert Legacy Root (G1) distrust by major browsers"}}]}
```

---

---
title: Entrust distrust by major browsers
description: Chrome and Mozilla have announced they will no longer trust Entrust certificates. Read about this change and how you can use Cloudflare to reduce impact.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Entrust distrust by major browsers

Google Chrome and Mozilla have announced they will no longer trust certificates issued from Entrust's root CAs.

Since Entrust is not within the [certificate authorities](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) used by Cloudflare, this change may only affect customers who upload [custom certificates](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) issued by Entrust.

## The decision

New Entrust certificates issued on **November 12, 2024 or after** will not be trusted on Chrome by default. And new Entrust certificates issued on **December 1, 2024 or after** will not be trusted on Mozilla by default.

Refer to the announcements ([Chrome ↗](https://security.googleblog.com/2024/06/sustaining-digital-certificate-security.html), [Mozilla ↗](https://groups.google.com/a/mozilla.org/g/dev-security-policy/c/jCvkhBjg9Yw?pli=1)) for a full list of roots that will be distrusted.

## Entrust's response

To prevent their customers from facing issues, Entrust has partnered with SSL.com, a different certificate authority, trusted by both Chrome and Mozilla.

This means that Entrust certificates will be issued using SSL.com roots.

## Cloudflare-managed certificates

Since Cloudflare also [partners with SSL.com](https://developers.cloudflare.com/ssl/reference/certificate-authorities/), you can switch from uploading custom certificates to using Cloudflare-managed certificates. This change brings the following advantages:

* Use [Advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) to have more control and flexibility while also benefitting from automatic renewals.
* Enable [Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/) to automatically issue certificates for your [proxied hostnames](https://developers.cloudflare.com/dns/proxy-status/).
* Use [Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/) to reduce manual intervention when renewing certificates for [partial (CNAME) setup](https://developers.cloudflare.com/dns/zone-setups/partial-setup/) zones.
* If you are a SaaS provider, extend the benefits of automatic renewals to your customers by specifying SSL.com as the certificate authority when [creating](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/) or [editing](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) your custom hostnames (API only).

## More resources

* [Use Cloudflare with SSL.com certificates](https://developers.cloudflare.com/ssl/reference/certificate-authorities/)
* [Google Security Blog ↗](https://security.googleblog.com/2024/06/sustaining-digital-certificate-security.html)
* [Entrust TLS Certificate Information Center ↗](https://www.entrust.com/tls-certificate-information-center)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/migration-guides/","name":"Migration guides"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/reference/migration-guides/entrust-distrust/","name":"Entrust distrust by major browsers"}}]}
```

---

---
title: TLS protocols
description: Explore Cloudflare's support for TLS protocols from 1.0 to 1.3. Learn about differences, security standards, and recommendations on what version to use.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# TLS protocols

Cloudflare supports the following TLS protocols:

* TLS 1.0
* TLS 1.1
* TLS 1.2
* TLS 1.3

TLS 1.0 is the [version that Cloudflare sets by default](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/minimum-tls/) for all customers using certificate-based encryption.

For information about which cipher suites are supported between clients and the Cloudflare network, refer to [Cipher suites](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/).

## Understand TLS versions

A higher TLS version implies a stronger cryptographic standard. TLS 1.2 includes fixes for known vulnerabilities found in previous versions.

As of June 2018, TLS 1.2 is the version required by the Payment Card Industry (PCI) Security Standards Council. Cloudflare recommends migrating to TLS 1.2 to comply with the PCI requirement.

[TLS 1.3](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/tls-13/), which offers additional security and performance improvements, was approved by the Internet Engineering Task Force (IETF) in May 2018.

PayPal's TLS 1.2 requirement

Using Cloudflare does not affect PayPal's TLS 1.2 requirement. However, note that PayPal IPN (Instant Payment Notification) might not support [TLS version 1.3](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/tls-13/). If you are encountering issues with PayPal IPN when the traffic is proxied by Cloudflare, try setting the [Minimum TLS version](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/minimum-tls/) to 1.2.

## Decide which version to use

TLS 1.3 has become widely adopted. As a general rule, Cloudflare recommends setting TLS to 1.3, as it will provide the best security.

However, not all browser versions support TLS 1.2 and above. Depending on your particular business situation, this may present some limitations in using stronger encryption standards:

* Consider using TLS 1.0 or 1.1 for sites with a broad user base, particularly non-transactional sites. In this way, you minimize the possibility that some clients cannot connect to your site securely.
* For a narrow user base and sites that run internal applications or business and productivity applications, Cloudflare recommends TLS 1.2\. These sites might already have more stringent security requirements or might be subject to [PCI compliance](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/compliance-status/). You also need to ensure that your users upgrade to a TLS 1.2 compliant browser.

## Related resources

* [PCI compliance and vulnerabilities mitigation](https://developers.cloudflare.com/ssl/reference/compliance-and-vulnerabilities/)
* [Transport Layer Security ↗](https://www.cloudflare.com/learning/ssl/transport-layer-security-tls/)
* [PCI Security Standards Council ↗](https://www.pcisecuritystandards.org/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/protocols/","name":"TLS protocols"}}]}
```

---

---
title: Cloudflare Waiting Room
description: Queue visitors in a virtual waiting room during traffic surges.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare Waiting Room

A virtual waiting room to manage peak traffic.

 Business and above 

Cloudflare Waiting Room allows you to route excess users of your website to a customized waiting room, helping preserve customer experience and protect origin servers from being overwhelmed with requests.

---

## Benefits

Waiting Room protects your origin server by preventing surges in legitimate traffic that may overload your origin.

Waiting Room also benefits your visitors by:

* Keeping your application online and preventing them from reaching error pages.
* Showing estimated wait times that are continuously updated.
* Opening up new spots more quickly by tracking dynamic inflow and [outflow](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/#session-duration).
* Remembering each visitor's status to prevent someone from losing their place in line or having to re-queue if they leave your site.
* Appearing in your own [branding and style](https://developers.cloudflare.com/waiting-room/how-to/customize-waiting-room/), which enhances trust and lets you provide additional information as needed.

---

## Features

###  Scheduled Event 

Customize the behavior of a waiting room for a specific period of time.

[ Use Scheduled Event ](https://developers.cloudflare.com/waiting-room/additional-options/create-events/) 

###  Waiting Room Rules 

Create rules to indicate specific traffic or areas of your site or application that you do not want a waiting room to apply to.

[ Use Waiting Room Rules ](https://developers.cloudflare.com/waiting-room/additional-options/waiting-room-rules/) 

###  Waiting Room Analytics 

Get insights into the traffic going through your waiting room.

[ Use Waiting Room Analytics ](https://developers.cloudflare.com/waiting-room/waiting-room-analytics/) 

###  Additional hostname and path coverage 

Apply a single waiting room to multiple hostnames and paths within the same zone.

[ Use Additional hostname and path coverage ](https://developers.cloudflare.com/waiting-room/how-to/place-waiting-room/) 

---

## Related products

**[Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/)** 

Cloudflare for SaaS allows you to extend the security and performance benefits of Cloudflare’s network to your customers via their own custom or vanity domains.

**[Rules](https://developers.cloudflare.com/rules/)** 

Cloudflare Rules allows you to make adjustments to requests and responses, configure Cloudflare settings, and trigger specific actions for matching requests.

**[SSL/TLS](https://developers.cloudflare.com/ssl/)** 

Cloudflare SSL/TLS encrypts your web traffic to prevent data theft and other tampering.

---

## Availability

The following customers have access to Cloudflare Waiting Room:

* Those qualified under [Project Fair Shot ↗](https://www.cloudflare.com/fair-shot/)
* Customers on a Business or Enterprise plan

Access to certain features depends on a customer's [plan type](https://developers.cloudflare.com/waiting-room/plans/).

Note

Enterprise customers can preview this product as a [non-contract service](https://developers.cloudflare.com/billing/understand/preview-services/), which provides full access, free of metered usage fees, limits, and certain other restrictions.

---

## Prerequisites

* [Cloudflare’s CDN](https://developers.cloudflare.com/cache/) is required to use the Waiting Room feature.
* Configure a [proxied DNS record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) or a [proxied load balancer](https://developers.cloudflare.com/load-balancing/understand-basics/proxy-modes/) for the waiting room’s hostname. A DNS record is not auto-configured after a waiting room is created.
* Visitors must enable cookies. Refer to [Waiting Room cookies](https://developers.cloudflare.com/waiting-room/reference/waiting-room-cookie/) for information on how cookies are used in Cloudflare Waiting Room.

---

## More resources

[Pricing](https://www.cloudflare.com/plans/) 

Explore pricing options for Waiting Room.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}}]}
```

---

---
title: About
description: How Cloudflare Waiting Room queues visitors during traffic surges.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# About

Waiting Room queues visitors when your traffic approaches a previously defined threshold that might otherwise bring an application down.

![Waiting Room process flow showing how a request is managed by Cloudflare and placed in a waiting room before reaching the origin website](https://developers.cloudflare.com/_astro/waiting-room-process-flow.BQ9hOmEi_1dE16C.webp) 

## User flow

Once you have [created and activated a waiting room](https://developers.cloudflare.com/waiting-room/get-started/) for a specific application page:

* If a page is not experiencing heavy traffic, a visitor accesses the page directly.
* If page traffic approaches a [user-defined threshold](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/#session-duration), a visitor enters a virtual waiting room until it is their turn to access the page:  
   * Each user receives a [cookie](https://developers.cloudflare.com/waiting-room/reference/waiting-room-cookie/) to manage the dynamic outflow of requests from the waiting room to the origin website in [First In First Out (FIFO)](https://developers.cloudflare.com/waiting-room/reference/queueing-methods/#first-in-first-out-fifo) order.  
   * While in the waiting room, the user's browser automatically refreshes every 20 seconds to give them updated information about their estimated wait time.  
   * When a user exits the waiting room and reaches your application, they can leave and re-enter without waiting for the length of time specified by the [session duration](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/#session-duration).  
   * Because waiting rooms support dynamic inflow and [outflow](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/#session-duration), new spots appear more quickly and estimated wait times are lower and more accurate.

## Architecture

Waiting Room is built on [Workers](https://developers.cloudflare.com/workers/) that runs across a global network of Cloudflare data centers.

When a request comes to a host or path covered by a Waiting Room, that request goes to a Waiting Room Worker in the closest geographic data center. The Worker then needs to make a decision: whether to send users to the queue or the website.

That decision itself depends on two factors: [admin-defined thresholds](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/) and the Waiting Room state.

For admin-defined thresholds, the two measures that matter are `total active users` and `new users per minute`:

* `total active users` is a target threshold for how many simultaneous users you want to allow on the pages covered by your waiting room.
* `new users per minute` defines the target threshold for the maximum rate of user influx to your website per minute.

A sharp spike in either of these values might result in queuing. Another configuration that affects how we calculate `the total active users` is `session duration`. A user is considered active for `session duration` minutes since the request is made to any page covered by a waiting room.

The other factor is the Waiting Room state, which is maintained at the local data center level but then also changes continuously based on the traffic around the world. Each data center works with its own Waiting Room state. This state is a snapshot of the traffic pattern for the website around the world available at that point in time. The advantage of using this approach - making decisions at the Worker level - is that we can make decisions without any significant latency added to the request. The algorithm for Waiting Room dynamically allocates a certain number of slots available to each Worker based on the Waiting Room state. Queueing starts when the slots run out within the Worker. The lack of additional latency added enables the customers to turn on the waiting room all the time without worrying about extra latency to their users.

The Waiting Room state is updated with global information every few seconds. We have a pipeline set up in Cloudflare [Durable Objects](https://developers.cloudflare.com/durable-objects/) that ensures changes in traffic get propagated around the world. This architecture ensures that we do not introduce additional latency, as well as that we are making decisions with as near-time accuracy as possible.

For even more details about the architecture and why we made these decisions, refer to our [deep-dive technical blog ↗](https://blog.cloudflare.com/how-waiting-room-queues).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/about/","name":"About"}}]}
```

---

---
title: Get started
description: Create and configure a Cloudflare Waiting Room.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

---

## Before you begin

Before you start this tutorial, make sure you have:

* Reviewed the [About](https://developers.cloudflare.com/waiting-room/about/) Waiting Room page.).
* Reviewed your [rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/) to make sure they allow at least one request every 20 seconds (required for automatic page refreshes).

---

## Step 1 — Plan out your waiting room

Before you create your waiting room, think about how you want it to appear and operate.

### Location

Which page will you cover with a waiting room? You can only have one waiting room per page, so you need to identify the high-traffic areas of your website.

Specify the URL for your page by setting the `hostname` and `path` in your [configuration settings](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/).

Advanced Waiting Room customers can also [specify multiple hostname and path combinations](https://developers.cloudflare.com/waiting-room/how-to/place-waiting-room/) for the same zone.

### Access method

You can direct visitors to your high-traffic page:

* Directly (via URL)
* Indirectly (via [a redirect](https://developers.cloudflare.com/rules/url-forwarding/bulk-redirects/))

### Queue activation

When you [activate your waiting room](#step-3--activate-your-waiting-room), choose whether:

* [**All visitors**](#queue-all-visitors) to be queued, in preparation for a product release or other time-based event.
* Only [**some visitors**](#queue-some-visitors) to be queued, as traffic reaches the thresholds defined in `Total active users` and `New users per minute`.

## Step 2 — Create your waiting room

Create your waiting room by:

* Using the [dashboard](https://developers.cloudflare.com/waiting-room/how-to/create-waiting-room/).
* Using the [API](https://developers.cloudflare.com/waiting-room/how-to/create-waiting-room/).

### Appearance (optional)

Some customers can [customize the design](https://developers.cloudflare.com/waiting-room/how-to/customize-waiting-room/) of their waiting room by editing the page's HTML and CSS.

If you have this ability, think about how you want the page to appear.

### Prepare your waiting room for mobile application traffic

If you need to manage traffic in a non-browser environment such as a mobile app or web app, use a [JSON-friendly waiting room](https://developers.cloudflare.com/waiting-room/how-to/json-response/) that can be consumed via your API endpoints. Note that if you have a mobile app or web app that depends on resources that would be protected by a waiting room, you will need to update those clients to handle Waiting Room appropriately.

## Step 3 — Activate your waiting room

Depending on your [queue activation](#queue-activation), you may deploy your waiting room differently.

### Queue some visitors

To queue visitors only when necessary:

1. Go to **Traffic** \> **Waiting Room**.
2. On a waiting room, set **Enabled** to **On**.
3. Your waiting room will begin queueing visitors once it approaches the target traffic thresholds defined in [**Total active users**](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/) and in [**New users per minute**](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/).

### Queue all visitors

To queue all visitors prior to a time-based offering, set up a pre-queue as part of a [waiting room event](https://developers.cloudflare.com/waiting-room/additional-options/create-events/#create-an-event-from-the-dashboard).

To start queueing all new visitors without a scheduled event:

1. Go to **Traffic** \> **Waiting Room**.
2. On a waiting room:  
   1. Ensure **Enabled** is set to **On**.  
   2. Set **Queue-all** to **On**.
3. Your waiting room will begin queueing all new visitors and will not allow any new visitors to the path protected by your waiting room. Queue-all will override all other waiting room settings, including event settings.

Note

Only new visitors will be queued. Active users that are already on your website will continue there and will not return to the queue until their session expires.

1. To begin allowing visitors to the path protected by your waiting room, set **Queue-all** to **Off**.

## Step 4 — Next steps

After you have created and deployed your first waiting room, you might also want to:

* [Test your waiting room](https://developers.cloudflare.com/waiting-room/additional-options/test-waiting-room/) before it goes live.
* [Monitor your traffic](https://developers.cloudflare.com/waiting-room/how-to/monitor-waiting-room/) in real time.
* [Troubleshoot](https://developers.cloudflare.com/waiting-room/troubleshooting/) potential issues.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/get-started/","name":"Get started"}}]}
```

---

---
title: Plans
description: Compare Waiting Room features available on each Cloudflare plan.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Plans

The features available for a waiting room depend on your plan type. You can only have **one plan** per zone.

One basic waiting room is included in all Business and Enterprise plans. On an Enterprise plan, you can purchase advanced waiting room(s) to unlock all of the additional advanced features.

| Free                                   | Pro | Business | Enterprise                |                                                                                       |
| -------------------------------------- | --- | -------- | ------------------------- | ------------------------------------------------------------------------------------- |
| Availability                           | No  | No       | Yes                       | Yes                                                                                   |
| Number of rooms                        | 0   | 0        | 1                         | 1 (default) _With advanced:_Custom (can purchase more)                                |
| Customized templates                   | No  | No       | No                        | Advanced add-on                                                                       |
| Queueing methods                       | No  | No       | First In First Out (FIFO) | First In First Out (FIFO) (default) _With advanced:_FIFO, Random, Reject, Passthrough |
| Configure multiple hostnames and paths | No  | No       | No                        | Advanced add-on                                                                       |
| Disable session renewal                | No  | No       | No                        | Advanced add-on                                                                       |
| JSON-friendly response                 | No  | No       | No                        | Advanced add-on                                                                       |
| Customize queuing status code          | No  | No       | Yes                       | Yes                                                                                   |
| Scheduled events                       | No  | No       | No                        | Advanced add-on                                                                       |
| Waiting Room rules                     | No  | No       | No                        | Advanced add-on                                                                       |
| Session Revocation                     | No  | No       | No                        | Advanced add-on                                                                       |
| SEO Crawler Bypassing                  | No  | No       | Yes                       | Yes                                                                                   |
| Turnstile Widget Mode                  | No  | No       | Invisible only            | Invisible (default) _With advanced:_Invisible, Managed, Non Interactive               |
| Turnstile Fail Action                  | No  | No       | Log only                  | Log only (default) _With advanced:_Log only & Infinite queue                          |

Note

Enterprise customers can preview this product as a [non-contract service](https://developers.cloudflare.com/billing/understand/preview-services/), which provides full access, free of metered usage fees, limits, and certain other restrictions.

## How do I get started?

To get started with Waiting Room, review our [setup guide](https://developers.cloudflare.com/waiting-room/get-started/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/plans/","name":"Plans"}}]}
```

---

---
title: Waiting Room Analytics
description: View waiting room queue depth, wait times, and visitor analytics.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Waiting Room Analytics

Waiting Room Analytics gives you historical insights into the traffic going through your waiting room compared to your waiting room settings. Data is stored for the past 30 days.

Using Waiting Room Analytics, you can:

* Evaluate peak traffic flow through your waiting room and onto your site.
* Determine how long users spent in the waiting room.
* Use analytics to help calibrate your waiting room settings.

## ​Dashboard Analytics

To access your waiting room’s analytics in the dashboard:

1. In the Cloudflare dashboard, go to the **Waiting Room** page.  
[ Go to **Waiting Room** ](https://dash.cloudflare.com/?to=/:account/:zone/traffic/waiting-rooms)
2. Expand the waiting room you would like to review metrics for, to display a preview of your waiting room analytics. The preview gives you insights into peak traffic through your waiting room over the last 24 hours including: Maximum active users, Maximum queued users and Typical time in queue for queued users.
3. Select **View More** under the Waiting Room Analytics section to get more historical analytics for your waiting room.
4. The time range for all of the metrics displayed defaults to the last 24 hours. To change the time range, select from the drop down. You can select any time range from the last 30 days that is a minimum of 30 minutes.

## Event Analytics

If your waiting room has a completed scheduled event, you can quickly access the event’s analytics by expanding the row for the waiting room you are interested in and selecting the event time. The link opens the analytics view for that waiting room, including information from the pre-queueing period to the end of the event.

To save this event information, you can either select **Download data** or **Print report**. If you delete the event, the time period link will no longer appear in your dashboard. If you edit the timing of the event, the time period link will update as well.

If you do not get a link to your event’s analytics, one of the following may have happened:

* Your event has not happened yet.
* Your event started more than 30 days ago.

## Metrics

These are metrics available in the Analytics dashboard and how they are calculated.

### Time in queue

Time in queue summary values give you an insight into the user experience by indicating how long queued users spent waiting to enter your application. It displays the time waited for the typical user, as well as for those who waited the longest, for the time period you have selected. These values are an indicator of the impact your waiting room settings combined with the traffic to your waiting room had on wait times.

If wait times are higher than you would like, and you feel comfortable doing so, you could consider taking any or all of the following actions:

* Increase `total_active_users` configured value.
* Increase `new_users_per_minute` configured value.
* Decrease `session_duration`.
* Disable session renewal.

Note

Note that wait times are only calculated for users who went from the waiting room to your origin.

### Time on origin

Time on origin summary values estimate how long users spent on the pages covered by your waiting room before leaving. For the time period selected, you will have access to the estimated time spent on origin for the typical user, as well as the time on origin for those who spend the most time on your site. Keep in mind that if your session renewal is disabled and there is no active queueing, users are issued a new waiting room session every `session_duration` minutes. Therefore, these users may be staying for multiple sessions. The time on origin for these users restarts each time a session expires.

The following are some takeaways you could have depending on the time on origin values.

You may want to increase session duration, giving users more time to make subrequests, and/or enable session renewal if:

* You have session renewal disabled.
* You have frequent, active queueing with long wait times.
* The typical time on origin is around 70% of your configured session duration.

These may be indicators that users need more time to complete their desired tasks on your site.

You may want to decrease session duration and/or disable session renewal if:

* Your top 5% time on origin is less than 70% of your configured session duration.
* You are seeing high queue times and do not want to increase traffic limits.

These may be indicators that users do not need as much time on your site and are taking up spots on your origin.

### Active users vs. queued users

The Active users chart is a time series chart that displays the maximum active users on any URLs covered by your waiting room as well as maximum queued users. These values are shown compared to your configured active user target threshold.

A new user is a novel request made to any URLs covered by the waiting room. Waiting Room counts the request as new if no waiting room cookie is tied to the request. Once the request is made, a waiting room cookie is issued. If there is an active queue, the user will be considered a queued user. Once that user makes it through the queue and onto the site, they are now an active user and remain active as long as they keep making HTTP requests to waiting room URLs at least once every `session_duration` minutes.

To identify and hone in on peak traffic, select a longer time period, such as 30 days. Then, drag your cursor to the left and right of any time period you would like to check with more granularity to zoom in. You can zoom in until each bar represents a one minute interval. All other metrics on the page will update automatically to reflect the data behind the time period selected.

To check for more details about a particular moment in time, hover over a bar on the graph. This displays a tooltip which will indicate the following for the time period that bar represents:

* Maximum active users reached
* Maximum queued users reached
* Configured active user target values

Queueing may occur below your configured limits, and active users may sometimes exceed your configured limits. Refer to the [Queuing activation](https://developers.cloudflare.com/waiting-room/how-to/monitor-waiting-room/#queueing-activation) section for more information.

### New users per minute

The New users per minute chart shows how many new users per minute passed through the waiting room to your origin compared to your configured New users per minute target threshold. Like the Active users chart, you can zoom in by highlighting to the left and right of the time period you are interested in, which will update the other chart as well as summary values. As you zoom out, each data point is averaged. Therefore, as you zoom in, values may fluctuate.

### Turnstile Widget Traffic

The Turnstile widget traffic chart shows the number of challenges issued per minute and the distribution of traffic seen with these challenges. Traffic is categorized into three main categories:

* Likely Human - This represents the number of challenges that were successfully solved.
* Likely Bots - This represents the number of unsolved challenges.
* Bots - This represents the number of failed challenges.

If your waiting room has the infinite queue option enabled, you will see a line on the graph representing the number of refresh requests from bots in the infinite queue.

## ​​GraphQL Analytics

You can query your Waiting Room analytics data via GraphQL API. Waiting Room analytics provides near real-time visibility into your Waiting Room, allowing you to visualize the traffic to your application and how it is managed respecting the configured limits.

Here are some query examples to get started:

Fetch values for total active users and new users per minute over a certain period.

This is a simple query to fetch metrics values. You can filter the data with the zone tag and query the `waitingRoomAnalyticsAdaptive` dataset. In this example, we have applied this query only on two metrics, but you can explore the schema and fetch the raw values from the GraphQL dataset without applying any aggregation methods.

Request

```

{

  viewer {

    zones(filter: {zoneTag: "example-zone"}) {

      waitingRoomAnalyticsAdaptive(limit: 3, filter: {datetime_gt: "2023-03-05T19:14:30Z", datetime_lt: "2023-03-07T19:13:00Z", waitingRoomId: "example-waiting-room-id"}) {

        totalActiveUsers

          newUsersPerMinutes

      }

    }

  }


```

Response

```

{

  "data": {

    "viewer": {

      "zones": [

        {

          "waitingRoomAnalyticsAdaptive": [

            {

              "newUsersPerMinute": 77,

              "totalActiveUsers": 1023

            },

            {

              "newUsersPerMinute": 113,

              "totalActiveUsers": 1009

            },

            {

              "newUsersPerMinute": 99,

              "totalActiveUsers": 927

            }

          ]

        }

      ]

    }

  },

  "errors": null

}


```

Find the average of total active users and new users per minute over a certain period, and aggregate this data over a period of 15 minutes.

This query calculates the average of total active users and new users per minute. The time dimension in the query is 15 minutes, therefore the data is aggregated over 15 minutes for the selected time period.

Request

```

{

  viewer {

    zones(filter: {zoneTag: "example-zone"}) {

      waitingRoomAnalyticsAdaptiveGroups(limit: 10, filter: {datetime_geq: "2023-03-15T04:00:00Z", datetime_leq: "2023-03-15T04:45:00Z", waitingRoomId: "example-waiting-room-id"}, orderBy: [datetimeFifteenMinutes_ASC]) {

        avg {

          totalActiveUsers

          newUsersPerMinute

        }

        dimensions {

          datetimeFifteenMinutes

        }

      }


```

Response

```

{

  "data": {

    "viewer": {

      "zones": [

        {

          "waitingRoomAnalyticsAdaptiveGroups": [

            {

              "avg": {

                "newUsersPerMinute": 119,

                "totalActiveUsers": 1180

              },

              "dimensions": {

                "datetimeFifteenMinutes": "2023-03-15T04:00:00Z"

              }

            },

            {

              "avg": {

                "newUsersPerMinute": 146,

                "totalActiveUsers": 961

              },

              "dimensions": {

                "datetimeFifteenMinutes": "2023-03-15T04:15:00Z"

              }

            },

            {

              "avg": {

                "newUsersPerMinute": 144,

                "totalActiveUsers": 1015

              },

              "dimensions": {

                "datetimeFifteenMinutes": "2023-03-15T04:30:00Z"

              }

            }

          ]

        }

      ]

    }

  },

  "errors": null

}


```

Find the weighted averages of time on origin (50th percentile) and total time waited (90th percentile) for a certain period and aggregate this data over one hour.

This query calculates the weighted averages of the metrics for a certain period of time aggregated hourly.

Request

```

{

  viewer {

    zones(filter: {zoneTag: "example-zone"}) {

      waitingRoomAnalyticsAdaptiveGroups(limit: 10, filter: {datetime_geq: "2023-03-15T04:00:00Z", datetime_leq: "2023-03-15T04:45:00Z", waitingRoomId: "example-waiting-room-id"}, orderBy: [datetimeHour_ASC]) {

        avgWeighted {

          timeOnOriginP50

          totalTimeWaitedP90

        }

        dimensions {

          datetimeHour

        }

      }


```

Response

```

{

  "data": {

    "viewer": {

      "zones": [

        {

          "waitingRoomAnalyticsAdaptiveGroups": [

            {

              "avgWeighted": {

                "timeOnOriginP50": 99.19,

                "totalTimeWaitedP90": 1625.63

              },

              "dimensions": {

                "datetimeHour": "2023-03-15T04:00:00Z"

              }

            }

          ]

        }

      ]

    }

  },

  "errors": null

}


```

## Why is there no data for my waiting room?

If you are not seeing any historical data for your waiting room, one or more of the following may be true:

* Your waiting room was not receiving any traffic for the time period you are inspecting.
* Your waiting room was not enabled for the time period you are inspecting.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/waiting-room-analytics/","name":"Waiting Room Analytics"}}]}
```

---

## List waiting rooms for account or zone

**get** `/{accounts_or_zones}/{account_or_zone_id}/waiting_rooms`

Lists waiting rooms for account or zone.

### Path Parameters

- `account_id: optional string`

  The Account ID to use for this endpoint. Mutually exclusive with the Zone ID.

- `zone_id: optional string`

  The Zone ID to use for this endpoint. Mutually exclusive with the Account ID.

### Query Parameters

- `page: optional number`

  Page number of paginated results.

- `per_page: optional number`

  Maximum number of results per page. Must be a multiple of 5.

### Returns

- `errors: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

- `result: optional array of WaitingRoom`

  - `id: optional string`

  - `additional_routes: optional array of AdditionalRoutes`

    Only available for the Waiting Room Advanced subscription. Additional hostname and path combinations to which this waiting room will be applied. There is an implied wildcard at the end of the path. The hostname and path combination must be unique to this and all other waiting rooms.

    - `host: optional string`

      The hostname to which this waiting room will be applied (no wildcards). The hostname must be the primary domain, subdomain, or custom hostname (if using SSL for SaaS) of this zone. Please do not include the scheme (http:// or https://).

    - `path: optional string`

      Sets the path within the host to enable the waiting room on. The waiting room will be enabled for all subpaths as well. If there are two waiting rooms on the same subpath, the waiting room for the most specific path will be chosen. Wildcards and query parameters are not supported.

  - `cookie_attributes: optional CookieAttributes`

    Configures cookie attributes for the waiting room cookie. This encrypted cookie stores a user's status in the waiting room, such as queue position.

    - `samesite: optional "auto" or "lax" or "none" or "strict"`

      Configures the SameSite attribute on the waiting room cookie. Value `auto` will be translated to `lax` or `none` depending if **Always Use HTTPS** is enabled. Note that when using value `none`, the secure attribute cannot be set to `never`.

      - `"auto"`

      - `"lax"`

      - `"none"`

      - `"strict"`

    - `secure: optional "auto" or "always" or "never"`

      Configures the Secure attribute on the waiting room cookie. Value `always` indicates that the Secure attribute will be set in the Set-Cookie header, `never` indicates that the Secure attribute will not be set, and `auto` will set the Secure attribute depending if **Always Use HTTPS** is enabled.

      - `"auto"`

      - `"always"`

      - `"never"`

  - `cookie_suffix: optional string`

    Appends a '_' + a custom suffix to the end of Cloudflare Waiting Room's cookie name(__cf_waitingroom). If `cookie_suffix` is "abcd", the cookie name will be `__cf_waitingroom_abcd`. This field is required if using `additional_routes`.

  - `created_on: optional string`

  - `custom_page_html: optional string`

    Only available for the Waiting Room Advanced subscription. This is a template html file that will be rendered at the edge. If no custom_page_html is provided, the default waiting room will be used. The template is based on mustache ( https://mustache.github.io/ ). There are several variables that are evaluated by the Cloudflare edge:

    1. {{`waitTimeKnown`}} Acts like a boolean value that indicates the behavior to take when wait time is not available, for instance when queue_all is **true**.
    1. {{`waitTimeFormatted`}} Estimated wait time for the user. For example, five minutes. Alternatively, you can use:
    1. {{`waitTime`}} Number of minutes of estimated wait for a user.
    1. {{`waitTimeHours`}} Number of hours of estimated wait for a user (`Math.floor(waitTime/60)`).
    1. {{`waitTimeHourMinutes`}} Number of minutes above the `waitTimeHours` value (`waitTime%60`).
    1. {{`queueIsFull`}} Changes to **true** when no more people can be added to the queue.

    To view the full list of variables, look at the `cfWaitingRoom` object described under the `json_response_enabled` property in other Waiting Room API calls.

  - `default_template_language: optional "en-US" or "es-ES" or "de-DE" or 35 more`

    The language of the default page template. If no default_template_language is provided, then `en-US` (English) will be used.

    - `"en-US"`

    - `"es-ES"`

    - `"de-DE"`

    - `"fr-FR"`

    - `"it-IT"`

    - `"ja-JP"`

    - `"ko-KR"`

    - `"pt-BR"`

    - `"zh-CN"`

    - `"zh-TW"`

    - `"nl-NL"`

    - `"pl-PL"`

    - `"id-ID"`

    - `"tr-TR"`

    - `"ar-EG"`

    - `"ru-RU"`

    - `"fa-IR"`

    - `"bg-BG"`

    - `"hr-HR"`

    - `"cs-CZ"`

    - `"da-DK"`

    - `"fi-FI"`

    - `"lt-LT"`

    - `"ms-MY"`

    - `"nb-NO"`

    - `"ro-RO"`

    - `"el-GR"`

    - `"he-IL"`

    - `"hi-IN"`

    - `"hu-HU"`

    - `"sr-BA"`

    - `"sk-SK"`

    - `"sl-SI"`

    - `"sv-SE"`

    - `"tl-PH"`

    - `"th-TH"`

    - `"uk-UA"`

    - `"vi-VN"`

  - `description: optional string`

    A note that you can use to add more details about the waiting room.

  - `disable_session_renewal: optional boolean`

    Only available for the Waiting Room Advanced subscription. Disables automatic renewal of session cookies. If `true`, an accepted user will have session_duration minutes to browse the site. After that, they will have to go through the waiting room again. If `false`, a user's session cookie will be automatically renewed on every request.

  - `enabled_origin_commands: optional array of "revoke"`

    A list of enabled origin commands.

    - `"revoke"`

  - `host: optional string`

    The host name to which the waiting room will be applied (no wildcards). Please do not include the scheme (http:// or https://). The host and path combination must be unique.

  - `json_response_enabled: optional boolean`

    Only available for the Waiting Room Advanced subscription. If `true`, requests to the waiting room with the header `Accept: application/json` will receive a JSON response object with information on the user's status in the waiting room as opposed to the configured static HTML page. This JSON response object has one property `cfWaitingRoom` which is an object containing the following fields:

    1. `inWaitingRoom`: Boolean indicating if the user is in the waiting room (always **true**).
    1. `waitTimeKnown`: Boolean indicating if the current estimated wait times are accurate. If **false**, they are not available.
    1. `waitTime`: Valid only when `waitTimeKnown` is **true**. Integer indicating the current estimated time in minutes the user will wait in the waiting room. When `queueingMethod` is **random**, this is set to `waitTime50Percentile`.
    1. `waitTime25Percentile`: Valid only when `queueingMethod` is **random** and `waitTimeKnown` is **true**. Integer indicating the current estimated maximum wait time for the 25% of users that gain entry the fastest (25th percentile).
    1. `waitTime50Percentile`: Valid only when `queueingMethod` is **random** and `waitTimeKnown` is **true**. Integer indicating the current estimated maximum wait time for the 50% of users that gain entry the fastest (50th percentile). In other words, half of the queued users are expected to let into the origin website before `waitTime50Percentile` and half are expected to be let in after it.
    1. `waitTime75Percentile`: Valid only when `queueingMethod` is **random** and `waitTimeKnown` is **true**. Integer indicating the current estimated maximum wait time for the 75% of users that gain entry the fastest (75th percentile).
    1. `waitTimeFormatted`: String displaying the `waitTime` formatted in English for users. If `waitTimeKnown` is **false**, `waitTimeFormatted` will display **unavailable**.
    1. `queueIsFull`: Boolean indicating if the waiting room's queue is currently full and not accepting new users at the moment.
    1. `queueAll`: Boolean indicating if all users will be queued in the waiting room and no one will be let into the origin website.
    1. `lastUpdated`: String displaying the timestamp as an ISO 8601 string of the user's last attempt to leave the waiting room and be let into the origin website. The user is able to make another attempt after `refreshIntervalSeconds` past this time. If the user makes a request too soon, it will be ignored and `lastUpdated` will not change.
    1. `refreshIntervalSeconds`: Integer indicating the number of seconds after `lastUpdated` until the user is able to make another attempt to leave the waiting room and be let into the origin website. When the `queueingMethod` is `reject`, there is no specified refresh time —_it will always be **zero**.
    1. `queueingMethod`: The queueing method currently used by the waiting room. It is either **fifo**, **random**, **passthrough**, or **reject**.
    1. `isFIFOQueue`: Boolean indicating if the waiting room uses a FIFO (First-In-First-Out) queue.
    1. `isRandomQueue`: Boolean indicating if the waiting room uses a Random queue where users gain access randomly.
    1. `isPassthroughQueue`: Boolean indicating if the waiting room uses a passthrough queue. Keep in mind that when passthrough is enabled, this JSON response will only exist when `queueAll` is **true** or `isEventPrequeueing` is **true** because in all other cases requests will go directly to the origin.
    1. `isRejectQueue`: Boolean indicating if the waiting room uses a reject queue.
    1. `isEventActive`: Boolean indicating if an event is currently occurring. Events are able to change a waiting room's behavior during a specified period of time. For additional information, look at the event properties `prequeue_start_time`, `event_start_time`, and `event_end_time` in the documentation for creating waiting room events. Events are considered active between these start and end times, as well as during the prequeueing period if it exists.
    1. `isEventPrequeueing`: Valid only when `isEventActive` is **true**. Boolean indicating if an event is currently prequeueing users before it starts.
    1. `timeUntilEventStart`: Valid only when `isEventPrequeueing` is **true**. Integer indicating the number of minutes until the event starts.
    1. `timeUntilEventStartFormatted`: String displaying the `timeUntilEventStart` formatted in English for users. If `isEventPrequeueing` is **false**, `timeUntilEventStartFormatted` will display **unavailable**.
    1. `timeUntilEventEnd`: Valid only when `isEventActive` is **true**. Integer indicating the number of minutes until the event ends.
    1. `timeUntilEventEndFormatted`: String displaying the `timeUntilEventEnd` formatted in English for users. If `isEventActive` is **false**, `timeUntilEventEndFormatted` will display **unavailable**.
    1. `shuffleAtEventStart`: Valid only when `isEventActive` is **true**. Boolean indicating if the users in the prequeue are shuffled randomly when the event starts.
    1. `turnstile`: Empty when turnstile isn't enabled. String displaying an html tag to display the Turnstile widget. Please add the `{{{turnstile}}}` tag to the `custom_html` template to ensure the Turnstile widget appears.
    1. `infiniteQueue`: Boolean indicating whether the response is for a user in the infinite queue.

    An example cURL to a waiting room could be:

    curl -X GET "https://example.com/waitingroom" \
    -H "Accept: application/json"

    If `json_response_enabled` is **true** and the request hits the waiting room, an example JSON response when `queueingMethod` is **fifo** and no event is active could be:

    {
    "cfWaitingRoom": {
    "inWaitingRoom": true,
    "waitTimeKnown": true,
    "waitTime": 10,
    "waitTime25Percentile": 0,
    "waitTime50Percentile": 0,
    "waitTime75Percentile": 0,
    "waitTimeFormatted": "10 minutes",
    "queueIsFull": false,
    "queueAll": false,
    "lastUpdated": "2020-08-03T23:46:00.000Z",
    "refreshIntervalSeconds": 20,
    "queueingMethod": "fifo",
    "isFIFOQueue": true,
    "isRandomQueue": false,
    "isPassthroughQueue": false,
    "isRejectQueue": false,
    "isEventActive": false,
    "isEventPrequeueing": false,
    "timeUntilEventStart": 0,
    "timeUntilEventStartFormatted": "unavailable",
    "timeUntilEventEnd": 0,
    "timeUntilEventEndFormatted": "unavailable",
    "shuffleAtEventStart": false
    }
    }

    If `json_response_enabled` is **true** and the request hits the waiting room, an example JSON response when `queueingMethod` is **random** and an event is active could be:

    {
    "cfWaitingRoom": {
    "inWaitingRoom": true,
    "waitTimeKnown": true,
    "waitTime": 10,
    "waitTime25Percentile": 5,
    "waitTime50Percentile": 10,
    "waitTime75Percentile": 15,
    "waitTimeFormatted": "5 minutes to 15 minutes",
    "queueIsFull": false,
    "queueAll": false,
    "lastUpdated": "2020-08-03T23:46:00.000Z",
    "refreshIntervalSeconds": 20,
    "queueingMethod": "random",
    "isFIFOQueue": false,
    "isRandomQueue": true,
    "isPassthroughQueue": false,
    "isRejectQueue": false,
    "isEventActive": true,
    "isEventPrequeueing": false,
    "timeUntilEventStart": 0,
    "timeUntilEventStartFormatted": "unavailable",
    "timeUntilEventEnd": 15,
    "timeUntilEventEndFormatted": "15 minutes",
    "shuffleAtEventStart": true
    }
    }

  - `modified_on: optional string`

  - `name: optional string`

    A unique name to identify the waiting room. Only alphanumeric characters, hyphens and underscores are allowed.

  - `new_users_per_minute: optional number`

    Sets the number of new users that will be let into the route every minute. This value is used as baseline for the number of users that are let in per minute. So it is possible that there is a little more or little less traffic coming to the route based on the traffic patterns at that time around the world.

  - `next_event_prequeue_start_time: optional string`

    An ISO 8601 timestamp that marks when the next event will begin queueing.

  - `next_event_start_time: optional string`

    An ISO 8601 timestamp that marks when the next event will start.

  - `path: optional string`

    Sets the path within the host to enable the waiting room on. The waiting room will be enabled for all subpaths as well. If there are two waiting rooms on the same subpath, the waiting room for the most specific path will be chosen. Wildcards and query parameters are not supported.

  - `queue_all: optional boolean`

    If queue_all is `true`, all the traffic that is coming to a route will be sent to the waiting room. No new traffic can get to the route once this field is set and estimated time will become unavailable.

  - `queueing_method: optional "fifo" or "random" or "passthrough" or "reject"`

    Sets the queueing method used by the waiting room. Changing this parameter from the **default** queueing method is only available for the Waiting Room Advanced subscription. Regardless of the queueing method, if `queue_all` is enabled or an event is prequeueing, users in the waiting room will not be accepted to the origin. These users will always see a waiting room page that refreshes automatically. The valid queueing methods are:

    1. `fifo` **(default)**: First-In-First-Out queue where customers gain access in the order they arrived.
    1. `random`: Random queue where customers gain access randomly, regardless of arrival time.
    1. `passthrough`: Users will pass directly through the waiting room and into the origin website. As a result, any configured limits will not be respected while this is enabled. This method can be used as an alternative to disabling a waiting room (with `suspended`) so that analytics are still reported. This can be used if you wish to allow all traffic normally, but want to restrict traffic during a waiting room event, or vice versa.
    1. `reject`: Users will be immediately rejected from the waiting room. As a result, no users will reach the origin website while this is enabled. This can be used if you wish to reject all traffic while performing maintenance, block traffic during a specified period of time (an event), or block traffic while events are not occurring. Consider a waiting room used for vaccine distribution that only allows traffic during sign-up events, and otherwise blocks all traffic. For this case, the waiting room uses `reject`, and its events override this with `fifo`, `random`, or `passthrough`. When this queueing method is enabled and neither `queueAll` is enabled nor an event is prequeueing, the waiting room page **will not refresh automatically**.

    - `"fifo"`

    - `"random"`

    - `"passthrough"`

    - `"reject"`

  - `queueing_status_code: optional 200 or 202 or 429`

    HTTP status code returned to a user while in the queue.

    - `200`

    - `202`

    - `429`

  - `session_duration: optional number`

    Lifetime of a cookie (in minutes) set by Cloudflare for users who get access to the route. If a user is not seen by Cloudflare again in that time period, they will be treated as a new user that visits the route.

  - `suspended: optional boolean`

    Suspends or allows traffic going to the waiting room. If set to `true`, the traffic will not go to the waiting room.

  - `total_active_users: optional number`

    Sets the total number of active user sessions on the route at a point in time. A route is a combination of host and path on which a waiting room is available. This value is used as a baseline for the total number of active user sessions on the route. It is possible to have a situation where there are more or less active users sessions on the route based on the traffic patterns at that time around the world.

  - `turnstile_action: optional "log" or "infinite_queue"`

    Which action to take when a bot is detected using Turnstile. `log` will
    have no impact on queueing behavior, simply keeping track of how many
    bots are detected in Waiting Room Analytics. `infinite_queue` will send
    bots to a false queueing state, where they will never reach your
    origin. `infinite_queue` requires Advanced Waiting Room.

    - `"log"`

    - `"infinite_queue"`

  - `turnstile_mode: optional "off" or "invisible" or "visible_non_interactive" or "visible_managed"`

    Which Turnstile widget type to use for detecting bot traffic. See
    [the Turnstile documentation](https://developers.cloudflare.com/turnstile/concepts/widget/#widget-types)
    for the definitions of these widget types. Set to `off` to disable the
    Turnstile integration entirely. Setting this to anything other than
    `off` or `invisible` requires Advanced Waiting Room.

    - `"off"`

    - `"invisible"`

    - `"visible_non_interactive"`

    - `"visible_managed"`

- `result_info: optional object { count, page, per_page, 2 more }`

  - `count: optional number`

    Total number of results for the requested service.

  - `page: optional number`

    Current page within paginated list of results.

  - `per_page: optional number`

    Number of results per page of results.

  - `total_count: optional number`

    Total results available without any search parameters.

  - `total_pages: optional number`

    The number of total pages in the entire result set.

### Example

```http
curl https://api.cloudflare.com/client/v4/$ACCOUNTS_OR_ZONES/$ACCOUNT_OR_ZONE_ID/waiting_rooms \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "success": true,
  "result": [
    {
      "id": "699d98642c564d2e855e9661899b7252",
      "additional_routes": [
        {
          "host": "shop2.example.com",
          "path": "/shop2/checkout"
        }
      ],
      "cookie_attributes": {
        "samesite": "auto",
        "secure": "auto"
      },
      "cookie_suffix": "abcd",
      "created_on": "2014-01-01T05:20:00.12345Z",
      "custom_page_html": "{{#waitTimeKnown}} {{waitTime}} mins {{/waitTimeKnown}} {{^waitTimeKnown}} Queue all enabled {{/waitTimeKnown}}",
      "default_template_language": "es-ES",
      "description": "Production - DO NOT MODIFY",
      "disable_session_renewal": false,
      "enabled_origin_commands": [
        "revoke"
      ],
      "host": "shop.example.com",
      "json_response_enabled": false,
      "modified_on": "2014-01-01T05:20:00.12345Z",
      "name": "production_webinar",
      "new_users_per_minute": 200,
      "next_event_prequeue_start_time": "2021-09-28T15:00:00.000Z",
      "next_event_start_time": "2021-09-28T15:00:00.000Z",
      "path": "/shop/checkout",
      "queue_all": true,
      "queueing_method": "fifo",
      "queueing_status_code": 202,
      "session_duration": 1,
      "suspended": true,
      "total_active_users": 200,
      "turnstile_action": "log",
      "turnstile_mode": "off"
    }
  ],
  "result_info": {
    "count": 1,
    "page": 1,
    "per_page": 20,
    "total_count": 2000,
    "total_pages": 100
  }
}
```

---

---
title: FAQ
description: Answers to common Waiting Room questions and issues.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# FAQ

Below you will find answers to our most commonly asked questions about the Waiting Room.

* [Configuration](#configuration)
* [Features and products](#features-and-products)
* [User behavior](#user-behavior)
* [Monitor your waiting room](#monitor-your-waiting-room)

---

## Configuration

### Can I display my waiting room page in another language?

Yes. For more details, refer to [Customize a waiting room](https://developers.cloudflare.com/waiting-room/how-to/customize-waiting-room/).

### Why does my waiting room look different than how I designed it?

If you have [customized your waiting room template](https://developers.cloudflare.com/waiting-room/how-to/customize-waiting-room):

1. Preview your template before deploying it to production.
2. If you encounter any issues, check for proper syntax and a closing backslash (/).

Note

Only Enterprise customers can customize the appearance of their waiting room.

### What can I update when my waiting room is actively queueing?

You can update a [waiting room's template](https://developers.cloudflare.com/waiting-room/how-to/customize-waiting-room) and those changes will be visible to users in near-real time. We recommend these updates as a way to engage with users and provide updated information or expectations.

You can also update the [configuration settings](https://developers.cloudflare.com/waiting-room/reference/configuration-settings) of a waiting room, but only make these changes when necessary. These changes may impact the estimated wait time shown to end users and cause unnecessary confusion.

## Features and products

### Which features are included in my Waiting Room plan?

To check which features are available to different plan types, refer to [Plans](https://developers.cloudflare.com/waiting-room/plans/).

### How does Waiting Room interact with other Cloudflare products?

Some Cloudflare products run before a waiting room acts on traffic:

* DDoS Mitigation
* Web Application Firewall (WAF)
* Bot Management
* Page Rules

Other Cloudflare products run after a waiting room acts on traffic:

* Workers

## User behavior

### What happens if a user refreshes their tab when in a waiting room?

A manual tab refresh has no effect on a user's position in your waiting room.

However, if they close their tab and then try to access the application again during active queueing, they will lose their spot and have to go to the back of the queue.

### What happens if a queued user leaves the queue?

When a user joins the queue, they are placed into a bucket which is their general position in line. When a user leaves the queue (closes the browser or tab), their place in line is held for five minutes after the last refresh. This grace period allows users to keep their position in line if they experience a brief disconnection. After five minutes, the grace period expires and they are no longer counted as waiting in the queue.

## Monitor your waiting room

### Why do I observe a few users being queued in the dashboard?

Some users might be queued before your waiting room reaches is limit due to architectural designs. For more details on the behavior and how to fix it, refer to [​​Queueing activation](https://developers.cloudflare.com/waiting-room/how-to/monitor-waiting-room#queueing-activation).

### Why are some users not being queued in my waiting room?

If you notice users not being queued to your waiting room, make sure the path you defined exactly matches the path of your website.

The path is case-sensitive, so if you have a waiting room set up for `/Black-Friday-Sale` and users go to `/black-friday-sale`, they will bypass your waiting room.

For more details, refer to [Best practices](https://developers.cloudflare.com/waiting-room/reference/best-practices).

### Why are users being blocked from entering my waiting room?

If you have Rate Limiting, check your [rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/).

The Waiting Room queue page refreshes every 20 seconds by populating the refresh header. If you have a rule set to block requests from a specific IP within 20 seconds, the user in the waiting room will be blocked. Make sure your rules allow at least one request every 20 seconds.

Your user also might not have [cookies](https://developers.cloudflare.com/waiting-room/reference/waiting-room-cookie) enabled. If they do not enable cookies and your waiting room is actively queueing traffic, they will not reach your endpoint until the queueing stops.

### Why is the estimated wait time increasing for some users?

Estimated wait times may increase if the rate of users leaving your site decreases. The estimated wait time is updated upon each page refresh based on the most recently available information about the rate of slots opening up on your site and the number of users ahead of the user in line. To make this increase less likely, you could limit the amount of time users are allowed to spend on your site by disabling session renewal. Be aware that, if you change your traffic settings, estimated wait times will change as well.

### Why is `new users per minute` low when there is capacity available?

The `new users per minute` metric tracks how many users were accepted to the origin in the last minute. It is only incremented when a queued user refreshes and is accepted to the origin. If the waiting room queueing method is set to `fifo`, we will wait until all queued users in a minute-based bucket are accepted before moving to the next bucket. If many of the users in a bucket have abandoned the queue, then the waiting room must wait until their place in line expires before moving on to the next bucket. This can cause `new users per minute` to be low when only a small percentage of queued users are actually still waiting.

This is often noticed if there is a large amount of automated traffic which does not handle cookies properly. Since bots usually do not persist cookies from one request to the next, they end up counting as multiple inactive users in the queue and prevent full utilization of available slots. For this reason, we recommend leveraging [Bots Management](https://developers.cloudflare.com/bots/) products to keep bots out of the queue. Waiting Room Advanced customers can try our [Turnstile](https://developers.cloudflare.com/turnstile/) integration, which prevents bots from clogging the line by putting them in an infinite queue.

### Why are my Waiting Room analytics and Google analytics not matching?

Waiting Room relies on a session cookie to count and keep track of active users. The duration for which a user is considered active depends on the waiting room configuration. The key setting involved in this calculation is [session duration](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/#session-duration). By default, Waiting Room considers a user active from the time of their last request made with a session cookie, until the configured session duration elapses. Customers with an advanced Waiting Room setup can modify this behavior by [disabling session renewal](https://developers.cloudflare.com/waiting-room/how-to/control-user-session/#disable-session-renewal-to-limit-browsing-time) and/or explicitly [revoking sessions](https://developers.cloudflare.com/waiting-room/how-to/control-user-session/#revoke-a-users-session-using-origin-commands) using an origin command.

If the session duration is set to a higher value, a user who makes only a single request will be considered active for longer than they actually were. This can cause the `Total Active Users` metric to appear higher than the active users metric reported by Google Analytics for the same time period, as Google Analytics only counts users who made requests during that specific period.

For example, if the session duration is set to 30 minutes and you look at the last 10 minutes of active users in Google Analytics, the number of active users reported by Waiting Room will be higher, since it includes users from the last 30 minutes.

Another key difference is that Waiting Room runs on requests made to the origin, while Google Analytics requires a user-agent to run JavaScript (via Google Tag). Waiting Room creates new sessions and tracks user metrics based on the HTTP request path, without requiring any additional JavaScript execution by a user-agent. In contrast, Google Analytics requires user-agents to execute JavaScript and make a secondary request to report details to Google Analytics. If a large portion of the traffic is automated, it may not be captured by Google Analytics. However, Waiting Room analytics will count such traffic as new users and consider them active for the configured session duration.

### Why did my traffic exceed the New Users Per Minute threshold?

Waiting Room is a distributed system, and achieving perfect global counting in real time is challenging due to the time required for state propagation across data centers worldwide. The budgeting logic is structured around both data center-specific and global budgets. Data center budgets are allocated based on the historical traffic received by each data center, while global budgets (a portion of the total available budget) are maintained to allow new users to enter from any data center globally.

In the case of a rapid spike — rising to several thousand users within a minute — the global state propagation process takes approximately two minutes, resulting in a delay before all data centers become aware of the spike. If this information is not disseminated quickly enough to other locations, temporary overshooting may occur, particularly when lower limits are in place.

This occurs because the portion of the budget reserved for new users to enter a data center is equally available to all data centers. Until the usage of this budget is synchronized across all data centers, each data center may consume a portion that collectively exceeds 100% of the global budget allocated for new users.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/troubleshooting/","name":"FAQ"}}]}
```

---

---
title: Create scheduled events
description: Create scheduled events with custom waiting room settings.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Create scheduled events

When you want to customize the behavior of a waiting room for a specific period of time — such as changing the queueing method or increasing the total active users — set up a **scheduled event**. You can do this from the dashboard or via the API.

Any properties set on the event will override the default property on the waiting room for the duration of the event.

Note

Only some customers can support scheduled events with their waiting rooms. For more details, refer to our [Plans](https://developers.cloudflare.com/waiting-room/plans/) page.

## Create an event from the dashboard

1. Within your application, go to **Traffic** \> **Waiting Room**.
2. Expand a waiting room and select **Schedule event**.
3. Customize the details for your event: name the event, add a description (optional), and select a Start Date Time and an End Date Time.
4. You can also enable the pre-queueing — in this case you need to define a pre-queueing time. And you can also select **Shuffle at event start** and all users in the pre-queue will be randomly admitted at event start.  
Note  
Enabling pre-queuing will send all new users to your pre-queue during the pre-queueing time period. If you would like to also pre-queue users already active, make the pre-queueing time period longer than the session duration and disable session renewal in the **Settings** section. Once active users sessions expire, they will be placed into the pre-queue before your event starts.
5. Select **Next**.
6. In the **Settings** section, you can define new values for your Total active users, New users per minute, Session duration, Session Renewal, and Queueing Method. For each of these settings you also have the option to always inherit the values defined in your waiting room. With this option, if you change the settings of your base waiting room, the corresponding Event setting will update as well.  
Note  
If you choose to override the values of Total active users, you must also override the number of New users per minute, and vice versa.
7. Select **Next**.
8. In the customization section, you can select Always inherit your waiting room’s template (default) or you can override it with a Custom Event Template. In this case, you need to import your own template. Make sure to preview the result before continuing.
9. Select **Next** and review your Event details and settings.
10. Select **Save**.

Note

The waiting room must be set to enabled for the event to activate. If your event is set to enabled but your waiting room is not, the event will not activate.

In your waiting room page, in the **Next Event** column you can visualize the date of the next event scheduled. This columns will read `N/A` in case there is no event scheduled for that waiting room. You can always suspend, edit or delete your event.

Note

You have a limit of five events per waiting room. To create a new event after you have reached this limit, you can delete a previous event.

## Create an event via API

To create an event, make a [POST request](https://developers.cloudflare.com/api/resources/waiting%5Frooms/subresources/events/methods/create/) including [required and optional parameters](#parameters). Any properties set on the event will override the default property on the waiting room for the duration of the event.

If you are using a [custom template](https://developers.cloudflare.com/waiting-room/how-to/customize-waiting-room/#custom-waiting-room), you may want to add [relevant variables](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/update/) to your template (listed under the `json_response_enabled` parameter).

Note

If you need to create overlapping events, use different waiting rooms.

### Parameters

Though most parameters are identical to those in a regular waiting room, there are a few unique to creating an event. For a complete list of event settings, please refer to [Create an Event](https://developers.cloudflare.com/api/resources/waiting%5Frooms/subresources/events/methods/create/).

* `name` (required): Unique name with alphanumeric characters, hyphens, and underscores.
* `event_start_time` (required): ISO 8601 timestamp that marks the start of the event. At this time, queued users will be processed with the event's configuration. Must occur at least 1 minute before `event_end_time`.
* `event_end_time` (required): ISO 8601 timestamp that marks the end of the event.
* `shuffle_at_event_start`: If **true** and `prequeue_start_time` is not null, users in the prequeue will be shuffled randomly at the `event_start_time`. Commonly used to ensure fairness if your event is using a [**FIFO** queueing method](#set-up-a-lottery).
* `prequeue_start_time`: ISO 8601 timestamp that marks when to begin queueing all users before the event starts. Must occur at least **5 minutes before** `event_start_time`.
* `description`: A text description providing more detail about the event.
* `suspended`: If **true**, the event is ignored and traffic is handled based on the waiting room's typical configuration.

### Queueing methods

When setting up events, you may want to also adjust the default queueing methods for your waiting room.

Set the waiting room's queueing method to [**Passthrough**](https://developers.cloudflare.com/waiting-room/reference/queueing-methods/#passthrough) when you want to allow traffic normally, but then restrict traffic during a scheduled event.

Set the waiting room's queueing method to [**Reject**](https://developers.cloudflare.com/waiting-room/reference/queueing-methods/#reject) when you want to block all traffic normally, but then allow traffic during special events like signups or ticket sales.

## Set up a "lottery"

Set up a "lottery" system to reward all users who enter into the queue prior to your event start time.

Users who reach your application **during the prequeue period** are [randomly assigned](https://developers.cloudflare.com/waiting-room/reference/queueing-methods/#random) a place in line when the event starts. If the event uses [FIFO ordering](https://developers.cloudflare.com/waiting-room/reference/queueing-methods/#first-in-first-out-fifo), users who reach your application **after the prequeue period** are assigned places after users from the prequeue.

To set up a "lottery", include the [following parameters](#parameters) in your API request:

* `prequeue_start_time`
* `shuffle_at_event_start`

## Preview an event configuration

Since some properties set on an event will override the default property of a waiting room for the duration of an event, you should use the API to [preview an event configuration](https://developers.cloudflare.com/api/resources/waiting%5Frooms/subresources/events/subresources/details/methods/get/) before it begins.

This command shows you the event's configuration as if it were active, meaning that inherited fields from the waiting room will display their current values.

## Edit an event

To edit an event, use a [PATCH request](https://developers.cloudflare.com/api/resources/waiting%5Frooms/subresources/events/methods/edit/).

## Disable events

You can disable an event by setting its `suspended` parameter to `true`.

Additionally, events will not become active if a waiting room itself is **Disabled**.

## Schedule a maintenance page

Follow these steps if you would like to deploy a scheduled maintenance page, with no queueing before or after the maintenance window.

1. [Create a waiting room](https://developers.cloudflare.com/waiting-room/how-to/create-waiting-room/) with [Passthrough](https://developers.cloudflare.com/waiting-room/reference/queueing-methods/#passthrough) queueing method enabled.
2. Create a waiting room event for this room with [Reject](https://developers.cloudflare.com/waiting-room/reference/queueing-methods/#reject) queueing method enabled.

After the scheduled event has ended, users will have access to your site. You can end the maintenance window before the scheduled event is over by setting the event to disabled.

## Other API commands

| Function                                                                                                                   | Command |
| -------------------------------------------------------------------------------------------------------------------------- | ------- |
| [Get event details](https://developers.cloudflare.com/api/resources/waiting%5Frooms/subresources/events/methods/get/)      | GET     |
| [List scheduled events](https://developers.cloudflare.com/api/resources/waiting%5Frooms/subresources/events/methods/list/) | GET     |
| [Delete event](https://developers.cloudflare.com/api/resources/waiting%5Frooms/subresources/events/methods/delete/)        | DELETE  |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/additional-options/create-events/","name":"Create scheduled events"}}]}
```

---

---
title: Embed in an iFrame
description: Embed a waiting room page inside an iFrame.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Embed in an iFrame

Because of how a waiting room [tracks visitor progress](#background), you need to [specify certain cookie attributes](#allow-cookies-to-pass-through-iframes) to properly embed a waiting room in an iFrame.

## Background

The [SameSite attribute of a cookie ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie#samesitesamesite-value) specifies whether that cookie can be shared with other domains that load on the same page (ad banners, iFrames). By default, browsers do not send cookies on cross-site subrequests to prevent attackers from stealing or manipulating information present in your cookies.

However, this behavior can prevent a waiting room from queueing a user properly if that waiting room is embedded in an iFrame. The waiting room depends on the [\_\_cfwaitingroom cookie](https://developers.cloudflare.com/waiting-room/reference/waiting-room-cookie/) to track a user in the queue. But, since the browser blocks the cookie from reaching the waiting room by default, an active and queueing waiting room cannot queue the user and will never let them access the application.

## Available options

To customize how your waiting room responds to cookies, include the `cookie_attributes` object when you [create a waiting room](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/create/) (only available via the API).

Available options include:

* `samesite`: Configures the `SameSite` attribute on the waiting room cookie:  
   * **auto** (default): Meant to be as flexible as possible, defaulting to **lax** but becoming **none** if you have enabled [**Always Use HTTPS**](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/).  
   * **lax**: Cookies are not sent on typical cross-site subrequests (for example to load images or frames into a third party site), but are sent when a user is navigating to the origin site  
   * **strict**: Cookies will only be sent in a first-party context.  
   * **none**: Cookies will always be sent.
* `secure`: Configures the `Secure` attribute on the waiting room cookie, which requires the request to be made over `https`:  
   * **auto** (default): Meant to be as flexible as possible, defaulting to **never** but becoming **always** if you have enabled [**Always Use HTTPS**](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/).  
   * **always**: Cookies can only be sent using `https` requests.  
   * **never**: Cookies can be sent using `http` or `https` requests.

## Allow cookies to pass through iFrames

If you are embedding a waiting room in an iFrame, specify the following values on `cookie_attributes` object when [creating a waiting room](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/create/) (only available via the API):

* `samesite`: `none`
* `secure`: If you have [**Always Use HTTPS**](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/) enabled, set to `auto`. If you have it disabled, set to `always`.

### Example

Request

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Waiting Rooms Write`

Create waiting room

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/waiting_rooms" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "name": "shop_waiting_room",

    "description": "Waiting room for webshop",

    "host": "shop.example.com",

    "path": "/shop",

    "queue_all": true,

    "new_users_per_minute": 200,

    "total_active_users": 300,

    "session_duration": 1,

    "disable_session_renewal": false,

    "json_response_enabled": false,

    "queueing_method": "FIFO",

    "cookie_attributes": {

        "samesite": "none",

        "secure": "auto"

    }

  }'


```

Response

```

{

  "success": true,

  "errors": [],

  "messages": [],

  "result": [

    {

      "id": "1111111111111111111111",

      "created_on": "2021-01-01T05:20:00.12345Z",

      "modified_on": "2021-01-01T05:20:00.12345Z",

      "name": "shop_waiting_room",

      "description": "Waiting room for webshop",

      "host": "shop.example.com",

      "path": "/shop",

      "queue_all": true,

      "new_users_per_minute": 200,

      "total_active_users": 300,

      "session_duration": 1,

      "disable_session_renewal": false,

      "json_response_enabled": false,

      "queueing_method": "FIFO",

      "cookie_attributes": {

        "samesite": "none",

        "secure": "auto"

      }

    }

  ]

}


```

## Limitations

Major web browsers have introduced restrictions on third-party cookies, which happen to be the same type of cookies used by waiting rooms within iframes. Waiting Room uses [Cookies Having Independent Partitioned State (CHIPS) ↗](https://developer.mozilla.org/en-US/docs/Web/Privacy/Privacy%5Fsandbox/Partitioned%5Fcookies) to work around these restrictions, but there are some drawbacks:

* A user viewing the waiting room both within an iframe and outside the iframe will be treated as two separate users, with each instance potentially exiting the queue at different times and counting separately in analytics.
* For a waiting room to be embedded in an iframe, both the embedded page and the embedding page must be accessed over HTTPS.
* CHIPS is not supported on Safari or Safari-derived browsers, like Orion and most iOS browsers, unless they have third-party cookie blocking disabled in their settings. These users will be stuck at the end of the queue, unable to progress until the queue is empty, and may count multiple times in analytics.

In general, if there is an issue setting and retrieving the waiting room cookie, you should expect users to be stuck at the end of the queue, and counting as multiple users in analytics.

These limitations may not apply if the embedded page and embedding page share a common domain name. For example, a page at `example.com` embedding a waiting room at `shop.example.com` may be considered first party by browsers, and not subject to third-party cookie restrictions.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/additional-options/embed-waiting-room-in-iframe/","name":"Embed in an iFrame"}}]}
```

---

---
title: Combine with Cloudflare for SaaS
description: Use Waiting Room with Cloudflare for SaaS custom hostnames.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Combine with Cloudflare for SaaS

If your application is using a custom hostname — meaning your SaaS provider is using [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/) — your application can support a waiting room.

## Applications on Cloudflare

If your application is already using Cloudflare, create a waiting room using the [typical process](https://developers.cloudflare.com/waiting-room/how-to/create-waiting-room/).

## Applications not on Cloudflare

If your application is not using Cloudflare, you need to ask your SaaS provider to configure a waiting room on [your Cloudflare for SaaS zone](https://developers.cloudflare.com/waiting-room/how-to/place-waiting-room/#custom-hostnames).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/additional-options/ssl-for-saas/","name":"Combine with Cloudflare for SaaS"}}]}
```

---

---
title: Test a waiting room
description: Follow this tutorial to test your waiting room behavior in response to load. To accurately simulate traffic, run your test script or planner for a period of time longer than a minute, ideally more than 2-3 minutes.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Test a waiting room

Follow this tutorial to test your waiting room behavior in response to load. To accurately simulate traffic through your waiting room with a load test, run your test script or planner for a period of time longer than a minute, ideally more than 2-3 minutes. You can run a load test using a variety of tools including [loader.io ↗](http://loader.io), [jmeter ↗](http://jmeter.apache.org), and [postman.com ↗](http://postman.com). You can also write a plain shell script to simulate user requests (each representing a distinct user).

Warning

This tutorial uses an open-sourced load testing tool that is not created or supported by Cloudflare.

---

## Before you begin

Before you start this tutorial, ensure you have:

* Reviewed the [About](https://developers.cloudflare.com/waiting-room/about/) Waiting Room page.
* For this tutorial, we will use an open source tool from Apache, [JMeter ↗](https://jmeter.apache.org/). You can download the binary from [JMeter's website ↗](https://jmeter.apache.org/download%5Fjmeter.cgi).

---

## 1\. Download sample script

First, download the [sample ↗](https://github.com/yj7o5/cf-waiting-room-testing/blob/main/plan.jmx) JMeter plan (configuration file) from GitHub.

This sample plan simulates 200 active users visiting the site, slowly ramping up traffic within the first minute and then maintaining 200 active users for the next three minutes. The test plan for this tutorial follows the setup outlined in the next steps.

## 2\. Edit and run the sample plan

Before running the sample plan, edit the waiting room in the test plan to point to your own waiting room.

1. Select **Waiting Room Simulation** to expand the test plan and then select **Request origin with waiting room** to update the test configuration.
![Select Request origin with waiting room in the Waiting Room Simulation panel](https://developers.cloudflare.com/_astro/simulation-panel.BOynNfQl_20776m.webp) 
1. In the **HTTP Request** section update the **Protocol**, **Server Name or IP**, and **Path** fields to point to your test URL with waiting room enabled. For example, if your full URL looks like `https://www.example.com/deals/summer`, then the fields should match as the following:

| Field             | Value                                       |
| ----------------- | ------------------------------------------- |
| Protocol          | https                                       |
| Server Name or IP | [www.example.com ↗](http://www.example.com) |
| Path              | deals/summer                                |

![Update the HTTP Request section](https://developers.cloudflare.com/_astro/http-request-section.DlSKTrFb_Z4WyLu.webp) 

Then, select the **play** button to get the test started. This should take roughly around 3-4 minutes.

![Select the play button](https://developers.cloudflare.com/_astro/navigation.CqQsxXoC_Z1zxoei.webp) 
* Each simulated user has the following attributes:  
   * Contains a Cookie jar for cookies persistence.  
   * Repeats for 20 times.  
         * Makes a request to the origin site with waiting room enabled.  
         * Logs request details.  
         * Pauses for 10 seconds before refreshing the page to make another request to the origin site.
![User attributes](https://developers.cloudflare.com/_astro/user-attributes.CMfB7b6L_6qoKz.webp) 

Per the plan above, each [Thread Group ↗](https://jmeter.apache.org/usermanual/test%5Fplan.html#thread%5Fgroup) performs the above action once. The user traffic ramps up within the first minute and keeps a sustained traffic for the next three minutes before users leave the site. You can send more or less traffic than what is being sent in this example by updating these properties.

![Visualizing number of threads](https://developers.cloudflare.com/_astro/threads.BTLucBgH_fTIip.webp) 

## 3\. Analyze results

To analyze the results of your test, you can query Waiting Room Analytics (Beta) via Cloudflare’s GraphQL API to check Total Active Users and Queued Users for each minute of your load test.

Example Curl Statement

Terminal window

```

echo '{

  "operationName": "UsersQueuedOverTimeQuery",

  "variables": {

    "filter": {

      "datetime_geq": "2022-10-17T15:34:00Z",

      "datetime_leq": "2022-10-17T15:40:00Z",

      "waitingRoomId": "<YOUR_WAITING_ROOM_ID>"

    },

    "zoneId": "<YOUR_ZONE_ID>"

  },

  "query": "query UsersQueuedOverTimeQuery($zoneId: string, $filter: ZoneWaitingRoomAnalyticsAdaptiveGroupsFilter_InputObject) {\n  viewer {\n    zones(filter: {zoneTag: $zoneId}) {\n      timeseries: waitingRoomAnalyticsAdaptiveGroups(limit: 5000, filter: $filter, orderBy: [datetimeMinute_ASC]) {\n        avg {\n          totalActiveUsers\n          totalActiveUsersConfig\n          totalQueuedUsers\n          __typename\n        }\n        max {\n          totalQueuedUsers\n          totalActiveUsers\n          totalActiveUsersConfig\n          __typename\n        }\n        min {\n          totalActiveUsersConfig\n          __typename\n        }\n        dimensions {\n          ts: datetimeMinute\n          __typename\n        }\n        __typename\n      }\n      total: waitingRoomAnalyticsAdaptiveGroups(limit: 1, filter: $filter) {\n        max {\n          totalQueuedUsers\n          totalActiveUsers\n          __typename\n        }\n        __typename\n      }\n      __typename\n    }\n    __typename\n  }\n}\n"

}' | tr -d '\n' | curl \

  -X POST


```

From our test, we got the following results (these are extracted from results of the query for readability):

* 15:35:00 UTC  
   * `"totalActiveUsers": 137,`  
   * `"totalActiveUsersConfig": 300,`  
   * `"totalQueuedUsers": 0`
* 15:36:00 UTC  
   * `"totalActiveUsers": 200,`  
   * `"totalActiveUsersConfig": 300,`  
   * `"totalQueuedUsers": 0`
* 15:37:00 UTC  
   * `"totalActiveUsers": 200,`  
   * `"totalActiveUsersConfig": 300,`  
   * `"totalQueuedUsers": 0`
* 15:38:00 UTC  
   * `"totalActiveUsers": 200,`  
   * `"totalActiveUsersConfig": 300,`  
   * `"totalQueuedUsers": 0`

The first minute mark, 15:35:00 UTC, shows 137 active users past the waiting room. This is because our traffic was set to gradually ramp up within the first minute and the test did not start exactly at the minute mark. When data was aggregated for the following minute, 15:36:00 UTC, the waiting room reported the total 200 users active we expected on the site as each “user” made subrequests. The active user count remained stable at 200 as long as it received subrequests from the traffic sent by the load test.

Note

Obtain your API token from the dashboard. Make sure your API token grants access to the **Analytics** resource. For more information on how to get the API token, follow the [Configure Analytics API token](https://developers.cloudflare.com/analytics/graphql-api/getting-started/authentication/api-token-auth/) guide.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/additional-options/test-waiting-room/","name":"Test a waiting room"}}]}
```

---

---
title: Waiting Room Bypass Rules
description: Create rules to bypass the waiting room for specific traffic.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Waiting Room Bypass Rules

A Waiting Room Bypass Rule is a type of Waiting Room Rule built on Cloudflare’s Ruleset Engine and managed via the Waiting Room API. A Waiting Room Bypass Rule allows you to indicate specific traffic or areas of your site or application that you do not want a waiting room to apply to. Each bypass rule is created and managed at the individual waiting room level for precise control over your waiting room traffic.

To indicate where you want your bypass rules to apply, write [custom logic](https://developers.cloudflare.com/ruleset-engine/rules-language/) using the [fields](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/) available via the Cloudflare Ruleset Engine, except the following:

* `cf.threat_score` and fields starting with `cf.bot_management`
* HTTP response fields

Please be advised that the waiting room will not apply to all the traffic that matches the expressions written for bypass rules and will not be counted as active users. No Waiting Room features, including but not limited to, Event pre-queueing, Reject queueing method, or Queue-all will apply to this traffic. Be mindful of this when creating and enabling Bypass Waiting Room rules. Only use bypass rules for traffic you are confident will not overwhelm your origin or cause significant traffic surges.

Note

Only some customers can create Waiting Room rules. For more details, refer to our [Plans](https://developers.cloudflare.com/waiting-room/plans/) page.

## Common Use Cases

* **Path/URL Exclusion**: Bypass specific paths or URLs under the path you have configured for your waiting room, if you do not want your waiting room to apply to these paths.
* **Administrative Bypass**: Allow internal site administrators to always bypass the waiting room, commonly identified by IP addresses.
* **Geo-targeting**: Exclude certain countries from being queued.
* **Query String Exclusion**: Exclude specific query strings under the path you have configured for your waiting room.
* **Exclude file extensions**: Prevent waiting room from applying to certain file extensions, such as `.js` that you utilize on your waiting room HTML template so that they render properly.

### A note on subrequests

Along with the query string(s) or paths you would like to exclude, make sure to include in your expression any paths or file types that subrequests may be hitting so that these assets or paths do not have waiting room applied as well. Otherwise, these subrequests will be getting the waiting room cookie since they are still covered by the waiting room.

These could include anything like images, JavaScript files, CSS files, etc. You can also configure the rule to bypass the waiting room for any paths of a file type by bypassing if a request ends with `.js`, `.css`, `.png`, etc., so you do not have to manually configure each path those assets may be stored under.

Example condition: `ends_with(http.request.uri.path, ".js")`

## Create Waiting Room Bypass Rules in the dashboard

To create a new bypass rule:

1. In the Cloudflare dashboard, go to the **Waiting Room** page.  
[ Go to **Waiting Room** ](https://dash.cloudflare.com/?to=/:account/:zone/traffic/waiting-rooms)
2. Expand a waiting room and select **Manage rules**.
3. Select **Create new bypass rule**.
4. Enter a descriptive name for the rule in **Rule name**.
5. Under **When incoming requests match**, define the rule expression. Use the **Field** drop-down list to choose an HTTP property. For each request, the value of the property you choose for **Field** is compared to the value you specify for **Value** using the operator selected in **Operator**.
6. Under **Then**, the Bypass Waiting Room action is automatically selected. Before saving, review your expression and ensure that the traffic that matches your expression is the traffic that you do not want the waiting room to apply to.
7. To save and deploy your rule, select **Save and Deploy**. If you are not ready to deploy your rule, select **Save as Draft**.

### Operators and grouping symbols

* Comparison operators specify how values defined in an expression must relate to the actual HTTP request value for the expression to return true.
* Logical operators combine two expressions to form a compound expression and use order of precedence to determine how an expression is evaluated.
* Grouping symbols allows you to organize expressions, enforce operator precedence, and nest expressions.

For examples and usage, refer to [Operators and grouping symbols](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/) in the Rules language documentation.

## Manage Rules via the Waiting Room API

You can manage, delete, and create bypass rules for your waiting room via the [Waiting Room API’s](https://developers.cloudflare.com/api/resources/waiting%5Frooms/subresources/rules/methods/get/). A bypass rule is a Waiting Room Rule that utilizes the `bypass_waiting_room` action.

When creating a Bypass Waiting Room Rule via API, make sure you:

* Have already created and saved a waiting room you want the rule to apply to.
* Define the expression to indicate which traffic you would like to bypass your waiting room.
* Set the rule action to `bypass_waiting_room`.

Create a waiting room rule by appending the following endpoint in the Waiting Room API to the Cloudflare API base URL. New waiting room rules will be added after any existing rules.

```

POST zones/{zone_id}/waiting_rooms/{room_id}/rules


```

Configure your bypass rule with the following required and optional parameters:

* **Description** (optional) - Give your rule a description to help keep a record of the purpose of this bypass rule.
* **Expression** (required) - Define the rule expression indicating which traffic to apply the bypass rule to.
* **Action** (required) - Define the action to take when expression evaluates to true. Set this to `bypass_waiting_room`.
* **Enabled** (optional) - This will default to true. If you do not wish to deploy your rule, you must set this to false.

### ​​API Examples

Bypass a path under your waiting room and all of its subpaths

If your waiting room is configured at `example.com/` and you would like all traffic visiting `example.com/bypassme` and all of its subpaths. In this example, we also want to ensure any subrequests of `js`, `css`, or `png` from also bypass the waiting room to ensure all assets are loaded properly on the paths being bypassed. Note that in this example, all requests ending in `js`, `css` or `png` will bypass the waiting room regardless of the subpath. If this is not your intended use case, please alter the expression to suit your specific requirements and site architecture.

Create Waiting Room Rule

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/waiting_rooms/$WAITING_ROOM_ID/rules" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "description": "subpath bypass",

    "expression": "starts_with(http.request.uri.path, \"/bypassme\") or ends_with(http.request.uri.path, \".js\") or ends_with(http.request.uri.path, \".css\") or ends_with(http.request.uri.path, \".png\")",

    "action": "bypass_waiting_room"

  }'


```

Allow a defined list of IPs to bypass the waiting room

Create Waiting Room Rule

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/waiting_rooms/$WAITING_ROOM_ID/rules" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "description": "ip list bypass",

    "expression": "ip.src in $bypass_ip_list",

    "action": "bypass_waiting_room"

  }'


```

### Other API options for managing bypass rules

Through the Waiting Room API, you can also do the following to manage bypass rules by using the Waiting Room rules API calls:

* **List Waiting Room Rules**: Lists rules for a waiting room.
* **Replace Waiting Room Rules**: Replaces all rules for a waiting room.
* **Patch Waiting Room Rules**: Updates a rule for a waiting room.
* **Delete Waiting Room Rules**: Deletes a rule for a waiting room.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/additional-options/","name":"Additional options"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/additional-options/waiting-room-rules/","name":"Waiting Room Rules"}},{"@type":"ListItem","position":5,"item":{"@id":"/waiting-room/additional-options/waiting-room-rules/bypass-rules/","name":"Waiting Room Bypass Rules"}}]}
```

---

---
title: Glossary
description: Definitions for terms used across Waiting Room documentation.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Glossary

Review the definitions for terms used across Cloudflare's Waiting Room documentation.

| Term                 | Definition                                                                                                                                                                                                                                                                                                         |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| downtime             | Downtime is the duration during which a system, service, or equipment is not operational or unavailable for use.                                                                                                                                                                                                   |
| error page           | An error page is a webpage shown to users when they try to access a specific webpage or resource that is unavailable due to a server error, broken link, or other issues. It typically includes details about the encountered error and offers potential solutions or guidance to help users navigate the problem. |
| iFrame               | An iFrame, short for Inline Frame, is an HTML element used to embed and display external content within a webpage, allowing the incorporation of another document or web page seamlessly within the main document.                                                                                                 |
| JSON-friendly        | JSON-friendly refers to data or formats that are easily and naturally represented in JSON (JavaScript Object Notation), a lightweight data interchange format, without requiring complex transformations or modifications.                                                                                         |
| legitimate traffic   | Legitimate traffic refers to authorized and permissible network activity, data transmissions, or communications that adhere to established norms and rules within a given system or network.                                                                                                                       |
| non-browser traffic  | Non-browser traffic refers to data exchanges and communication occurring between devices or systems that do not involve web browsers, such as a mobile app or web apps.                                                                                                                                            |
| SEO crawlers         | SEO crawlers, or web crawlers, are automated programs employed by search engines to systematically browse and index web content, gathering information about the structure and relevance of pages to determine search result rankings.                                                                             |
| Set-Cookie           | Set-Cookie is an HTTP header used by web servers to send a cookie to a user's browser during an HTTP response, enabling the server to store information on the client side, often used for session management and user preferences.                                                                                |
| traffic management   | The process of controlling and optimizing the flow of network data to ensure efficient and reliable communication.                                                                                                                                                                                                 |
| virtual waiting room | A virtual waiting room is an online system or feature that manages and controls access to a website or service during periods of high traffic, preventing server overload by placing users in a queue until they can be accommodated, ensuring a more equitable and efficient user experience.                     |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/glossary/","name":"Glossary"}}]}
```

---

---
title: Control user session settings
description: Configure session duration and renewal settings.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Control user session settings

Adjust these settings to control how long a user can hold their place on your site after leaving the waiting room.

## Session duration

Once on your site, a user is considered active as long as they make an HTTP request to any URL covered by your waiting room once every **session duration** minutes. Each new request restarts a user’s time to stay active equal to **session duration**.

## Disable session renewal to limit browsing time

You can limit each user’s time on your site to only one session duration by checking the box next to Disable Session Renewal from the dashboard. Once a user has been active on your site for **session duration** minutes, if there is active queueing, that user will be sent to the back of the queue. If there is not an active queue when **session duration** minutes is over, this user will be given a new waiting room cookie and counted as a new user again.

## Revoke a user’s session using origin commands

To terminate a user's session when they perform a specific action, you can send a command to the waiting room using an HTTP header on the response from your origin. This command tells the waiting room to revoke the session of the user associated with the current response. This allows spots to open up more dynamically and may increase throughput from your queue.

To enable this feature in the Cloudflare Dashboard, check the box next to Allow session termination via origin commands from the dashboard. To enable this feature through the [Cloudflare API](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/update/), update the `enabled_origin_commands` property to include the value `”revoke”` in the list of enabled origin commands.

Then, to return a revocation origin command and revoke the user's session associated with the current request, add the `Cf-Waiting-Room-Command: revoke` HTTP header to the response from your origin.

To get the number of sessions revoked, you can query `sessionsRevoked` metrics from your [Waiting Room analytics](https://developers.cloudflare.com/waiting-room/waiting-room-analytics/#graphql-analytics) data via GraphQL API.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/how-to/control-user-session/","name":"Control user session settings"}}]}
```

---

---
title: Control waiting room traffic
description: Manage active user limits and queueing behavior.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Control waiting room traffic

To change whether and how traffic reaches a waiting room, update the values for **Enabled**, **Queue All**, and **Queueing Method** on your waiting room.

## Enable a waiting room

To enable a waiting room:

1. Go to **Traffic** \> **Waiting Room**.
2. On a waiting room, set **Enabled** to **On**.

## Queue options

By default, an active waiting room puts visitors in a queue when traffic approaches the target thresholds defined in **Total active users** and **New users per minute**. Refer to [Queueing activation](https://developers.cloudflare.com/waiting-room/how-to/monitor-waiting-room/#queueing-activation) for more information.

However, if you want all visitors to be queued for a predefined amount of time — in preparation for a product release or other time-based event — use the [Create scheduled events](https://developers.cloudflare.com/waiting-room/additional-options/create-events/) option.

You may also use the **Queue-all** option on a waiting room as an emergency stop to all traffic during unexpected or temporary downtime. As long as the waiting room is active and **Queue-all** is enabled, no traffic will reach your application.

### Queue visitors when necessary

To queue visitors only when necessary:

1. Go to **Traffic** \> **Waiting Room**.
2. On a waiting room, set **Enabled** to **On**.
3. Your waiting room will begin queueing visitors once it approaches the target traffic thresholds defined in [**Total active users**](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/) and in [**New users per minute**](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/).

### Queue all visitors

To queue all visitors prior to a time-based offering, set up a pre-queue as part of a [waiting room event](https://developers.cloudflare.com/waiting-room/additional-options/create-events/#create-an-event-from-the-dashboard).

To start queueing all new visitors without a scheduled event:

1. Go to **Traffic** \> **Waiting Room**.
2. On a waiting room:  
   1. Ensure **Enabled** is set to **On**.  
   2. Set **Queue-all** to **On**.
3. Your waiting room will begin queueing all new visitors and will not allow any new visitors to the path protected by your waiting room. Queue-all will override all other waiting room settings, including event settings.

Note

Only new visitors will be queued. Active users that are already on your website will continue there and will not return to the queue until their session expires.

1. To begin allowing visitors to the path protected by your waiting room, set **Queue-all** to **Off**.

## Queueing method

For more details about queueing method, refer to [Queueing methods](https://developers.cloudflare.com/waiting-room/reference/queueing-methods/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/how-to/control-waiting-room/","name":"Control waiting room traffic"}}]}
```

---

---
title: Create a waiting room
description: Create a new waiting room in the dashboard or via API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Create a waiting room

You can create a waiting room from the dashboard or via API.

Note

For additional context on creating a waiting room, refer to [Get started](https://developers.cloudflare.com/waiting-room/get-started/).

* [ Dashboard ](#tab-panel-11128)
* [ API ](#tab-panel-11129)

1. Within your application, go to **Traffic** \> **Waiting Room**.
2. Select **Create**.
3. Customize the [settings](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/) for your waiting room. For additional guidance refer to [Best practices](https://developers.cloudflare.com/waiting-room/reference/best-practices/).
4. Select **Next**.
5. In this section, you can choose whether to enable [Turnstile](https://developers.cloudflare.com/turnstile/) for your waiting room. If you select **Yes**, you will need to choose your [Widget mode](https://developers.cloudflare.com/turnstile/concepts/widget/) and define the action to take if a turnstile challenge fails. The available Widget modes and actions depend on your plan type. Refer to the [Plans](https://developers.cloudflare.com/waiting-room/plans/) for more details.
6. If you wish to [customize your waiting room](https://developers.cloudflare.com/waiting-room/how-to/customize-waiting-room/), update the HTML and CSS as needed. If you are using this waiting room to manage traffic for your mobile app or API, enable the JSON response toggle. Make sure that you have set up a [JSON friendly response](https://developers.cloudflare.com/waiting-room/how-to/json-response/) for your client (mobile or web app).
7. Select the **Queuing status code** to determine the HTTP status code that is returned when a user is in the waiting room.
8. Select **Next**.
9. Review your settings before saving. If you customized your waiting room, make sure to [preview the result](https://developers.cloudflare.com/waiting-room/how-to/customize-waiting-room/#preview-waiting-room).
10. Select **Save**. Your new waiting room will be enabled by default.

To create a Waiting Room using the API, send a [POST request](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/create/) to the `/zones/{zone_identifier}/waiting_rooms` endpoint:

* For parameter references, refer to [Configuration settings](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/)
* For authentication instructions, refer to [Create an API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/).
* For help with endpoints and pagination, refer to [Make API calls](https://developers.cloudflare.com/fundamentals/api/how-to/make-api-calls/).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Waiting Rooms Write`

Create waiting room

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/waiting_rooms" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "name": "shop_waiting_room",

    "description": "Waiting room for webshop",

    "host": "shop.example.com",

    "path": "/shop",

    "queue_all": true,

    "new_users_per_minute": 200,

    "total_active_users": 300,

    "session_duration": 1,

    "disable_session_renewal": false,

    "json_response_enabled": false,

    "queueing_method": "fifo",

    "queueing_status_code": 202,

    "cookie_attributes": {

        "samesite": "auto",

        "secure": "auto"

    }

  }'


```

The response contains the complete definition of the newly created Waiting Room.

Response

```

{

  "success": true,

  "errors": [],

  "messages": [],

  "result": [

    {

      "id": "1111111111111111111111",

      "created_on": "2023-01-01T05:20:00.12345Z",

      "modified_on": "2023-01-01T05:20:00.12345Z",

      "name": "shop_waiting_room",

      "description": "Waiting room for webshop",

      "host": "shop.example.com",

      "path": "/shop",

      "queue_all": true,

      "new_users_per_minute": 200,

      "total_active_users": 300,

      "session_duration": 1,

      "disable_session_renewal": false,

      "json_response_enabled": false,

      "queueing_method": "fifo",

      "queueing_status_code": 202,

      "cookie_attributes": {

        "samesite": "auto",

        "secure": "auto"

      }

    }

  ]

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/how-to/create-waiting-room/","name":"Create a waiting room"}}]}
```

---

---
title: Customize a waiting room
description: Customize the waiting room page with HTML templates.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Customize a waiting room

You can customize your waiting room from the dashboard or via API.

## Customize a waiting room from the dashboard

To design and preview the appearance of a waiting room, select the **Customization** tab in the **Create waiting room** page.

Cloudflare offers options to customize the appearance of your waiting room:

* [Default waiting room](#default-waiting-room): An unbranded waiting room that displays an estimated waiting time to visitors.  
   * Select a language for your default waiting room page. You can choose from the following languages: English, Arabic, German, Spanish, French, Indonesian, Italian, Japanese, Korean, Dutch, Polish, Portuguese (Brazilian), Turkish and Chinese (Simplified and Traditional).
* [Custom waiting room](#custom-waiting-room): Edit template text or create your own HTML code:  
   * Customize both HTML or CSS content, including fonts, colors, static images, additional languages and more.  
   * Edit content directly in the dashboard or import relevant files.
* [Return a JSON-friendly waiting room response](https://developers.cloudflare.com/waiting-room/how-to/json-response/): Toggle to also enable a JSON response with a user's status in the waiting room.

### Default waiting room

To choose the default, unbranded waiting room:

1. Select a waiting room.
2. Go to the **Customization** step.
3. Select **Default waiting room**.
4. Select the language for your waiting room default page.

### Custom waiting room

Note

Only certain customers can customize their waiting rooms. For more details, refer to our [Plans](https://developers.cloudflare.com/waiting-room/plans/) page.

To customize a waiting room:

1. Select a waiting room.
2. Go to the **Customization** step.
3. Select **Custom waiting room**.

You can edit the HTML code directly in the text box:

* Select **Download default template** to download a HTML file containing the default template content to your computer.
* Select **Download** to download a HTML file containing the text box content to your computer.
* Select **Copy** to copy the text from the text box to your clipboard, then paste it into an editor of your choice.

The template text contains [code to display the wait time](#display-wait-time). If you want to display the estimated wait time to visitors, do not delete this content.

#### Upload an HTML file

1. Select **Import** to upload a HTML file from your computer.
2. Select the file in the dialog and select **Open**. The HTML file size limit is 1,048,576 bytes (1 MB).

Make further edits in the text box. Include the [code to display the wait time](#display-wait-time) to display the estimated queue time on the waiting room page or create your own custom page using [available variables](#available-variables).

#### Display wait time

The following content in the `<main>` section of the template HTML code displays the wait time:

```

<h2 id="time-remaining">

  <noscript>

    {{#waitTimeKnown}}Your estimated wait time is {{waitTimeFormatted}}...{{/waitTimeKnown}}

    {{^waitTimeKnown}}{{#queueIsFull}}The estimated wait time is greater than a day. You will

    automatically be placed in the queue once space is available.{{/queueIsFull}}

    {{^queueIsFull}}Your estimated wait time is unavailable.{{/queueIsFull}}{{/waitTimeKnown}}

  </noscript>

</h2>


```

The following script within the `<body>` section after `<main>` fetches the wait time:

```

<script type="text/javascript">

  var remainingEl = document.getElementById('time-remaining');

  var waitTime = {{waitTime}};

  var waitTimeKnown = {{waitTimeKnown}};


  var remainingString = 'Your estimated wait time is ';


  if (!waitTimeKnown) {

    remainingString += 'unavailable.'

  } else {

    if (waitTime === 1) {

      remainingString += waitTime + ' minute...';

    } else {

      remainingString += waitTime + ' minutes...';

    }

  }


  remainingEl.innerText = remainingString;

</script>


```

#### Turnstile variable

If you are using Turnstile for your customized waiting room, you will need to ensure the `turnstile` variable is added. The default queuing page template and any newly created custom templates already include this variable. If you have an existing custom HTML template and wish to enable the Turnstile integration, you will need to add `{{{turnstile}}}` somewhere in the template to let Waiting Room know where the widget should be placed. Waiting Room uses Mustache templates, so including raw HTML within your template without escaping requires three curly braces instead of two.

```

<!DOCTYPE html>

<html>

  <head>

    <title>Waiting Room</title>

  </head>

  <body>

    <h1>You are currently in the queue.</h1>

    {{#waitTimeKnown}}

      <h2>Your estimated wait time is {{waitTimeFormatted}}.</h2>

    {{/waitTimeKnown}}

    {{^waitTimeKnown}}

      <h2>Your estimated wait time is unknown.</h2>

    {{/waitTimeKnown}}

    {{#turnstile}}

      <!-- for a managed (and potentially interactive) challenge, you may want to instruct the user to complete the challenge -->

      <p>Please complete this challenge so we know you're a human:</p>

      {{{turnstile}}} <!-- include the turnstile widget -->

    {{/turnstile}}

  </body>

</html>


```

When using Infinite Queue (especially with managed challenges which may be interactive), you may want to let users know that they will not be in the queue until they complete the challenge.

#### Available variables

When you create a waiting room with custom HTML, you can have access to several variables to customize your response. For a full list of variables, refer to the `json_response_enabled` parameter in the [Cloudflare API docs](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/create/).

#### Multiple-language support

Customizable waiting rooms can display text in any language supported by the UTF-8 character set. To display estimated wait time, you can use numeric variables like `waitTime` and `waitTimeHours` within your waiting room template, regardless of user language. However, at the time, the following variables are only available in English: `waitTimeFormatted`, `timeUntilEventStartFormatted`, and `timeUntilEventEndFormatted`.

If you would like to display different languages within your custom waiting room depending on path or subdomain, you can add JavaScript code to your custom HTML to do so. Below you can find a couple of starter templates that you can use as an example to start from:

* To display a different language based on path, download this [template](https://developers.cloudflare.com/waiting-room/static/index.path.html.txt). The template displays the content in English if the path contains `en` or as a default, Japanese if the path contains `jp`, French if the path contains `fr`, and Spanish if the path contains `es`.
* To display a different language based on subdomain, download this [template](https://developers.cloudflare.com/waiting-room/static/index.subdomain.html.txt). The template displays the content in English as a default or if the subdomain contains `en`, Japanese if the subdomain contains `jp`, French if the subdomain contains `fr`, and Spanish if the subdomain contains `es`.

Download either of these templates and customize them however you would like. Update the path or subdomain to reflect your site’s language selection structure. You may edit these templates to include other languages by adding translations to the `translations` object for each of the locales.

#### Resource hosting

If you are using images or other resources for your customized waiting room, **do not** host those assets on the hostname covered by your waiting room. Otherwise, any requests for these assets will not be able to pass through the waiting room.

### Preview waiting room

To preview the appearance of a waiting room:

1. In your application, go to **Traffic** \> **Waiting Room**.
2. Either [create a waiting room](https://developers.cloudflare.com/waiting-room/how-to/create-waiting-room/) or [edit an existing one](https://developers.cloudflare.com/waiting-room/how-to/edit-delete-waiting-room/).
3. Go to the **Review** step.
4. Select **Preview waiting room**:
* Choose **Queueing** to display the waiting room appearance when it is enabled on the dashboard and **Queue-all** is not enabled.
* Choose **Queue-All** to display the waiting room appearance when it is enabled on the dashboard and **Queue-all** is enabled. When **Queue-all** is enabled for a waiting room, the estimated wait time is not displayed.

### Troubleshooting

If you notice something unexpected when previewing your waiting room, review your custom code for proper syntax. Often, you might forget to close each tag with its appropriate closing tag (the tag name with a `/`).

## Customize a waiting room via API

You can use the Waiting Room API to customize the web page served to visitors when they are placed in a virtual waiting room.

In the following `PATCH` request, the `custom_page_html` field contains the HTML code for the [customized waiting room](https://developers.cloudflare.com/waiting-room/how-to/customize-waiting-room/):

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Waiting Rooms Write`

Patch waiting room

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/waiting_rooms/$WAITING_ROOM_ID" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "name": "webshop-waiting-room",

    "host": "example.com",

    "new_users_per_minute": 200,

    "total_active_users": 300,

    "custom_page_html": "<p>Include custom HTML here</p>"

  }'


```

Response:

```

{

  "success": true,

  "errors": [],

  "messages": [],

  "result": [

    {

      "id": "1111111111111111111111",

      "name": "webshop-waiting-room",

      "description": "Waiting room for webshop",

      "host": "example.com",

      "path": "/shop",

      "suspended": false,

      "queue_all": false,

      "new_users_per_minute": 200,

      "total_active_users": 300,

      "session_duration": 1,

      "disable_session_renewal": false,

      "json_response_enabled": false,

      "queueing_method": "FIFO",

      "cookie_attributes": {

        "samesite": "auto",

        "secure": "auto"

      },

      "custom_page_html": "<p>Include custom HTML here</p>",

      "created_on": "2014-01-01T05:20:00.12345Z",

      "modified_on": "2014-01-01T05:20:00.12345Z"

    }

  ]

}


```

### Preview the HTML code for a customized waiting room

Before making an API request to configure a waiting room web page with customized HTML, you can preview your custom HTML by uploading it to a preview endpoint:

```

POST https://api.cloudflare.com/client/v4/zones/{zone_id}/waiting_rooms/preview


```

In the request body, include the customized HTML content in the `custom_html` field:

```

{

  "custom_html": "<p>Include custom HTML here</p>"

}


```

Note that you pass HTML content to the preview endpoint in the `custom_html` field, but when you are using the API to configure a waiting room, you pass the HTML content in the `custom_page_html` field.

Example request:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Waiting Rooms Write`

Create a custom waiting room page preview

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/waiting_rooms/preview" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "custom_html": "<p>Include custom HTML here</p>"

  }'


```

The preview endpoint returns a temporary URL in the response body where you can preview your custom page:

```

{

  "result": {

    "preview_url": "https://waitingrooms.dev/preview/111111111111"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

You do not have to have a Cloudflare account to access the preview link, so you can validate the waiting room webpage on multiple devices.

### Preview the default or current waiting room web page

After [generating a preview URL](https://developers.cloudflare.com/api/resources/waiting%5Frooms/subresources/page/methods/preview/), use the following endpoint to generate a link to preview the currently configured web page for a waiting room, or the default page if no custom page is configured.

```

GET https://waitingrooms.dev/preview/{preview_id}


```

The link in the response displays the content of the `custom_page_html` field, rendered with [mustache ↗](https://mustache.github.io).

Use the optional `force_queue` query parameter to preview the waiting room web page when all traffic is force-queued.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/how-to/customize-waiting-room/","name":"Customize a waiting room"}}]}
```

---

---
title: Edit and delete waiting rooms
description: Edit or delete existing waiting rooms.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Edit and delete waiting rooms

You can manage your waiting rooms using the [Waiting Room dashboard](https://developers.cloudflare.com/waiting-room/how-to/waiting-room-dashboard/) or the [API](https://developers.cloudflare.com/waiting-room/reference/waiting-room-api/).

Note

For details about updating an active waiting room, refer to [Best practices](https://developers.cloudflare.com/waiting-room/reference/best-practices/).

## Use the dashboard

### Edit a waiting room

1. In your application, go to **Traffic** \> **Waiting Room**.
2. On a record, select **Edit**.
3. Select **Settings**.
4. Edit the settings. For a description of settings, refer to [Configuration settings](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/).
5. Select **Next**. If you have access to [customized templates](https://developers.cloudflare.com/waiting-room/how-to/customize-waiting-room/), you could also adjust the template.
6. Once you get to **Review**, select **Save**.

### Delete a waiting room

1. In your application, go to **Traffic** \> **Waiting Room**.
2. On a record, select **Delete**.
3. Select **Delete** again.

## Use the API

### Edit a waiting room

[Replace ↗](https://api.cloudflare.com#waiting-room-update-waiting-room) a configured waiting room by appending the following endpoint to the Cloudflare API base URL.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Waiting Rooms Write`

Update waiting room

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/waiting_rooms/$WAITING_ROOM_ID" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "name": "webshop-waiting-room",

    "host": "example.com",

    "new_users_per_minute": 200,

    "total_active_users": 300

  }'


```

[Update ↗](https://api.cloudflare.com#waiting-room-patch-waiting-room) a configured waiting room by appending the following endpoint to the Cloudflare API base URL.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Waiting Rooms Write`

Patch waiting room

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/waiting_rooms/$WAITING_ROOM_ID" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "name": "webshop-waiting-room",

    "host": "example.com",

    "new_users_per_minute": 200,

    "total_active_users": 300

  }'


```

You only need to include the fields you want to update in the payload of the PATCH request.

### Delete a waiting room

Delete a waiting room by appending the following endpoint in the [Waiting Room API ↗](https://api.cloudflare.com#waiting-room-delete-waiting-room) to the Cloudflare API base URL.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Waiting Rooms Write`

Delete waiting room

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/waiting_rooms/$WAITING_ROOM_ID" \

  --request DELETE \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/how-to/edit-delete-waiting-room/","name":"Edit and delete waiting rooms"}}]}
```

---

---
title: Get JSON response for mobile and other non-browser traffic
description: Return JSON responses for mobile apps and non-browser clients.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get JSON response for mobile and other non-browser traffic

If you need to manage traffic in a non-browser environment such as a mobile app or web app, Cloudflare provides a JSON-friendly waiting room that can be consumed via your API endpoints:

1. When a user is queued, we return our own JSON response.
2. When a user leaves the waiting room, we forward the request to your origin server and return the response from your origin server (be it JSON, XML, an HTML page, etc.).

Important

Turnstile is not supported for Waiting Room JSON responses. Turnstile challenges are only enforced for browser-based (HTML) responses. If your application relies on JSON responses (for example, mobile apps, APIs, or other non-browser traffic), Turnstile will be disabled and cannot be enabled for these requests.

In order to consume the waiting room response in the JSON format, take the following steps:

## Step 1 – Enable JSON response

To receive a JSON response, you first need to enable that option in your waiting room.

* **Via the dashboard**: When [customizing a waiting room](https://developers.cloudflare.com/waiting-room/how-to/customize-waiting-room/), enable **JSON Response**.
* **Via the API**: When [creating a waiting room](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/create/), set `json_response_enabled` to true.

## Step 2 – Get JSON data

Make a request to your waiting room endpoint with the header `Accept: application/json`. Note that the header has to match exactly `Accept: application/json`. If it is anything else or has any additional content such as `Accept: application/json, text/html` the response will not return in the JSON format. You must retry the request every `refreshIntervalSeconds` in order for users to advance in the queue.

Request

```

curl "https://example.com/waitingroom" \

--header "Accept: application/json"


```

Response

```

{

  "cfWaitingRoom": {

    "inWaitingRoom": true,

    "waitTime": 5,

    "waitTimeKnown": true,

    "waitTimeFormatted": "5 minutes",

    "queueIsFull": false,

    "queueAll": false,

    "lastUpdated": "2021-08-03T23:46:00.000Z",

    "refreshIntervalSeconds": 20

  }

}


```

## Cookies in the request header

Waiting Room is driven by a waiting room cookie that determines the position of the user in the queue. Because of this, the cookie is updated in the response headers for each request. For each request to an endpoint protected by Waiting Room, the application must include the up-to-date cookie retrieved during the previous request. This is mandatory regardless of a user having been queued or not. If a request does not include a cookie, the waiting room will assume this is a new user and will return a new cookie in the response header. Consequently, this will place the user at the end of the queue. Thus, when consuming the waiting room in a non-browser environment it is important to include the waiting room cookie in the request header and keep it updated after each request.

Refer to the [Waiting Room cookies](https://developers.cloudflare.com/waiting-room/reference/waiting-room-cookie/), for more information.

## Advancing in the queue

In a browser environment, the page automatically refreshes every `refreshIntervalSeconds` to ensure that the user advances in the queue. In a non-browser environment, where the Waiting Room JSON-friendly API is being consumed, it is expected that your backend service (or API) also refreshes/makes a request to the Waiting Room configured endpoint every `refreshIntervalSeconds` to ensure the advancing of the user in the queue.

These are some of the places where the JSON-friendly response can be consumed (this list is not exhaustive):

1. In a mobile app traffic  
   * **Integrate Waiting Room variables** – Create a new template in your mobile app to receive the JSON response. For a full list of these variables, refer to the `json_response_enabled` parameter in the [Cloudflare API docs](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/create/).  
   * **Allow cookies** – As mentioned above, a waiting room [requires cookies](https://developers.cloudflare.com/waiting-room/reference/waiting-room-cookie/), and your mobile app will need to support cookies. For ease of use, consider using a cookie manager like [CookieJar ↗](https://pkg.go.dev/net/http#CookieJar).  
   * **Consume JSON data** \- Make a request to the Waiting Room endpoint with the `Accept: application/json` header.
2. Inside Cloudflare Workers (or in your own backend service)  
   * **Integrate Waiting Room variables** – Expect a JSON response in your backend API. For a full list of these variables, refer to the `json_response_enabled` parameter in the [Cloudflare API docs](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/create/).  
   * **Include cookies in the request header** – As mentioned above, a waiting room [requires cookies](https://developers.cloudflare.com/waiting-room/reference/waiting-room-cookie/), and your backend API will need to support cookies. For ease of use, consider using a cookie manager like [CookieJar ↗](https://pkg.go.dev/net/http#CookieJar).  
   * **Enable JSON response** \- Via the dashboard or via the API.  
   * **Consume JSON data** \- Make a request to the Waiting Room endpoint with the `Accept: application/json` header.  
   Here is an example, demonstrating the usage of the waiting room endpoint inside a Worker. The request headers include the necessary `accept` and `cookie` header values that are required by the Waiting Room API. The accept header ensures that a JSON-friendly response is returned, if a user is queued. Otherwise, if the request is sent to the origin, then whatever the response origin returns gets returned back. In this example, a hardcoded `__cfwaitingroom` value is embedded in the cookie field. In a real-life application, however, we expect that a cookie returned by the Waiting Room API is used in each of the subsequent requests to ensure that the user is placed accordingly in the queue and let through to the origin when it is the users turn.

JavaScript

```

const waitingroomSite = "https://examples.cloudflareworkers.com/waiting-room";


export default {

  async fetch(request, env, ctx) {

    const init = {

      headers: {

        accept: "application/json",

        cookie: "__cfwaitingroom=F)J@NcRfUjXnZr4u7x!A%D*G-KaPdSgV",

      },

    };


    return fetch(waitingroomSite, init)

      .then((response) => response.json())

      .then((response) => {

        if (response.cfWaitingRoom.inWaitingRoom) {

          return Response("in waiting room", { "content-type": "text/html" });

        }

        return new Response(response);

      });

  },

};


```

Note

Only Advanced Waiting Room customers can support JSON-friendly format with their waiting rooms. For more details, refer to our [Plans page](https://developers.cloudflare.com/waiting-room/plans/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/how-to/json-response/","name":"Get JSON response for mobile and other non-browser traffic"}}]}
```

---

---
title: Monitor waiting room status
description: Monitor active users and queue status in real time.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Monitor waiting room status

You can monitor the status of your waiting rooms using the [dashboard](#status-in-the-dashboard) or the [API](#status-in-the-api).

Note that the **Total active users** and **Queued users** shown in the dashboard, as well as through API endpoints are estimates. That data corresponding to each of these metrics is cached for around 30 seconds after the time it takes to be synced from all data centers globally. Therefore, the status will range between 20-50 seconds in the past, depending on the exact moment the data was queried, aggregated, as well as the age of the cache.

Refer to [Waiting Room Analytics](https://developers.cloudflare.com/waiting-room/waiting-room-analytics/) for more details about the traffic going through your waiting room.

## Status in the dashboard

Open the **Waiting Room** dashboard to view the list of your waiting rooms.

The **Status** column displays the current state of the waiting room:

* **Not queueing**:  
   * Waiting room enabled, but has not reached traffic threshold to send visitors to waiting room.  
   * Shows estimated number of users in the application.
* **Queueing**:  
   * Waiting room enabled and sending visitors to waiting room.  
   * Shows estimated number of users in the queue.  
   * On hover, shows maximum wait time expected for users.
* **Disabled**: The waiting room is suspended.
* **Queue-all**:  
   * Forces all traffic to queue in the waiting room.  
   * On hover, shows estimated number of users in the queue.

## Status in the API

[Check whether traffic is queueing in a configured waiting room](https://developers.cloudflare.com/api/resources/waiting%5Frooms/subresources/statuses/methods/get/) by appending the following endpoint to the Cloudflare API base URL:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Waiting Rooms Read`
* `Waiting Rooms Write`

Get waiting room status

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/waiting_rooms/$WAITING_ROOM_ID/status" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

The response is:

* `queueing` if visitors are currently queueing in the waiting room.
* `not_queueing` if the room is empty or if the waiting room is suspended.

To check whether a configured waiting room is suspended or whether the traffic is force-queued to the waiting room, append the following endpoint to the Cloudflare API base URL.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Waiting Rooms Read`
* `Waiting Rooms Write`

Waiting room details

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/waiting_rooms/$WAITING_ROOM_ID" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

The endpoint above [fetches all settings](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/get/) for a configured waiting room:

Terminal window

```

      "success": true,

      "errors": [],

      "messages": [],

      "result": {

        "id": "REDACTED",

        "created_on": "2014-01-01T05:20:00.12345Z",

        "modified_on": "2014-01-01T05:20:00.12345Z",

        "name": "shop_waiting_room",

        "description": "Waiting room for webshop",

        "suspended": false,

        "host": "shop.example.com",

        "path": "/shop",

        "queue_all": true,

        "new_users_per_minute": 200,

        "total_active_users": 300,

        "session_duration": 1,

        "disable_session_renewal": false,

        "json_response_enabled": false,

        "queueing_method": "random",

        "cookie_attributes": {

          "samesite": "auto",

          "secure": "auto"

        },

        "custom_page_html": "{{#waitTimeKnown}} {{waitTime}} mins {{/waitTimeKnown}} {{^waitTimeKnown}} Queue all enabled {{/waitTimeKnown}}"

      }


```

The value of `suspended` indicates whether a waiting room is activated or suspended:

* `false`: The waiting room is activated.
* `true`: The waiting room is suspended.

The value of `queue_all` indicates whether all traffic is forced to queue in the waiting room:

* `false`: Visitors are diverted to the waiting room only if traffic exceeds the configured threshold.
* `true`: All traffic is forced to queue in the waiting room, and no traffic passes from the waiting room to the origin.

## Queueing activation

Waiting Room queues traffic at the data-center level to increase scalability, letting each data center make decisions independently.

Because of this design, the configured traffic limits of a waiting room are target values which your waiting room will work to keep your traffic volumes near. A waiting room might queue traffic from a specific data center before the waiting room reaches its limit of `new_users_per_minute` or `total_active_users`.

Waiting Room also continuously monitors the rate of users entering throughout each minute, and not just at the end of the minute. Therefore, if at the beginning of your minute, a large fraction of your set `new_users_per_minute` value already joined, we may start queueing users, even if the overall `new_users_per_minute` value that is reached for that minute is not hit.

To help prevent a waiting room from active queueing, increase the values for `new_users_per_minute` and/or `total_active_users`. For more information about how Waiting Room makes queueing decisions, review our [blogpost ↗](https://blog.cloudflare.com/how-waiting-room-queues).

Note

Note that Waiting Room is designed to handle legitimate traffic. If you notice frequent or abnormal queueing behavior, ensure that you are properly handling malicious and automated traffic using Cloudflare security products.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/how-to/monitor-waiting-room/","name":"Monitor waiting room status"}}]}
```

---

---
title: Place a waiting room
description: Place a waiting room on a specific path or hostname.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Place a waiting room

When [configuring a waiting room](https://developers.cloudflare.com/waiting-room/how-to/create-waiting-room/), you need to indicate which pages the waiting room will cover.

Your waiting room requires at least one hostname and path in its configuration settings. There is an implied wildcard after the path, meaning the waiting room will also apply to any subpaths. When there is an active queue, all new users will enter the queue at any URLs covered by this hostname and path combination. If you have multiple waiting rooms, the waiting room with the most specific subpath takes precedence.

## Apply to multiple hostnames and paths

Advanced Waiting Room customers can apply a single waiting room to multiple hostnames and paths. To do so via the UI, after adding the first hostname and path, select **Add Hostname and Path** and then input the next hostname and path combination you would like the waiting room to cover. If adding more than one hostname and path for a single waiting room, you must also create a unique waiting room cookie by filling out the Custom cookie field. To add multiple hostnames and paths via the API, utilize the `additional_routes` field and customize the cookie suffix with the `cookie_suffix` field.

You cannot add any hostname and path combinations already configured for another waiting room. Hostnames must belong to the zone that the waiting room is configured on.

A single waiting room can be applied to multiple custom hostnames as long as the following is true:

* The apex domain is the same between the custom hostnames
* Each custom hostname is [configured explicitly](#custom-hostnames) in SSL for SaaS setup.

## Custom hostnames

To deploy a waiting room to a custom hostname, the non-wildcard custom hostname must be [configured and active in SSL for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/create-custom-hostnames/). Then, [create](https://developers.cloudflare.com/waiting-room/how-to/create-waiting-room/) a Waiting Room and optionally apply it to [multiple hostnames](#apply-to-multiple-hostnames-and-paths) with the same apex domain.

This means that – if you want a waiting room for `hello.example.com` – `hello.example.com` must be an active custom hostname. You will not be able to create a waiting room at `hello.example.com` based on only `example.com` being set up as a custom hostname, even if you have enabled wildcards for this custom hostname in SSL for SaaS setup.

## Create exceptions to waiting room coverage

If there are subpaths or query strings of the path you have configured for your waiting room that you would not like the waiting room to apply to, you can create a [Waiting Room bypass rule](https://developers.cloudflare.com/waiting-room/additional-options/waiting-room-rules/bypass-rules/#common-use-cases) to ensure that traffic is not queued at these parts of your site.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/how-to/place-waiting-room/","name":"Place a waiting room"}}]}
```

---

---
title: Access Waiting Room
description: Access and manage waiting rooms in the Cloudflare dashboard.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Access Waiting Room

Use Cloudflare Waiting Room to create a holding area where users can queue to access a high-traffic area of your enterprise website. For an introduction, refer to the [Overview](https://developers.cloudflare.com/waiting-room/) page.

To access Waiting Room on the Cloudflare dashboard, go to the **Waiting Room** page.

[ Go to **Waiting Room** ](https://dash.cloudflare.com/?to=/:account/:zone/traffic/waiting-rooms) 

Use the dashboard to [create, edit, update, and delete](https://developers.cloudflare.com/waiting-room/how-to/) waiting rooms.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/how-to/waiting-room-dashboard/","name":"Access Waiting Room"}}]}
```

---

---
title: Best practices
description: Best practices for configuring and testing waiting rooms.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Best practices

Follow these best practices to avoid potential issues and improve the visitor experience.

## Total active users

When specifying the **Total active users** in your [configuration settings](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/), set the value to `75%` of your origin's traffic capacity.

## Page path

When setting the waiting room **Path** in your [configuration settings](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/), pay attention to potential subpaths. Waiting rooms are enabled on all subpaths, meaning you might be sending more traffic to your waiting room than anticipated.

Additionally, if you have multiple waiting rooms, the waiting room with the most specific subpath takes precedence.

## Update during active queueing

### Waiting room template

If you want to provide your users with updated information or expectations when they are queueing, Cloudflare recommends that you update your [waiting room template](https://developers.cloudflare.com/waiting-room/how-to/customize-waiting-room/). All changes will be visible to your users in close to real time.

### Configuration settings

When users are actively queueing, only make changes to your [configuration settings](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/) when necessary. These changes may impact the estimated wait time shown to end users, which might lead to user confusion.

### Queueing method

Though you can change your [queueing method](https://developers.cloudflare.com/waiting-room/reference/queueing-methods/), it may affect users if your waiting room is actively queueing:

* **From FIFO to Random**: Users will no longer be ordered based on their cookie timestamp, which may affect the displayed wait time.
* **From Random to FIFO**: Users will be ordered based on their cookie timestamp, meaning any new users move to the end of the FIFO queue.

Note

If you change the queueing method from FIFO > Random > FIFO, users will be ordered by their original entry time.

## Waiting Room and SEO

SEO crawlers may end up in a queue during active queueing. When this happens, your sites search results and SEO may be impacted. To avoid this, you can enable SEO Crawler Bypassing from the Waiting Room dashboard or via API. SEO Crawler Bypassing ensures that trusted SEO Crawlers, verified by Bot Management, are never placed in your waiting rooms. By not being queued, SEO crawlers are always able to crawl your site, which helps maintain your SEO and search results in major search engines.

By enabling this service, you understand that these verified crawlers are completely bypassing your waiting rooms. No waiting room settings or features will apply to this traffic.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/reference/best-practices/","name":"Best practices"}}]}
```

---

---
title: Configuration settings
description: Available configuration settings for waiting rooms.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configuration settings

You can customize a variety of options for your waiting rooms.

[ Dashboard settings ](#dashboard-settings) [ Additional details ](#additional-details) 

## Dashboard settings

| **Settings**                   | **Notes**                 |                                         |                                                                                                                                                                                                                                                                                                                               |                                                                                                                                                                                        |
| ------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Dashboard Setting**          | **API parameter**         | **Required?**                           | **Description**                                                                                                                                                                                                                                                                                                               | **Best practices**                                                                                                                                                                     |
| Name                           | name                      | Yes                                     | Unique waiting room name.                                                                                                                                                                                                                                                                                                     |                                                                                                                                                                                        |
| Hostname                       | host                      | Yes                                     | Hostname for which the waiting room will be applied (no wildcards).                                                                                                                                                                                                                                                           | Do not include http:// or https://.                                                                                                                                                    |
| Path                           | path                      | No                                      | Case-sensitive path of the waiting room. The waiting room will be enabled for all subpaths. Wildcards and query parameters are not supported.                                                                                                                                                                                 | If your server does not allow letter casing, use numbers in your path.                                                                                                                 |
| Additional Hostnames and Paths | additional\_routes        | No                                      | Add additional hostnames and/or paths to your waiting room coverage.                                                                                                                                                                                                                                                          | Additional hostnames must be within the same zone. Hostname and path combinations must be unique per waiting room.                                                                     |
| Custom Cookie Suffix           | cookie\_suffix            | Required when using additional\_routes. | Customize the suffix of your waiting room cookie. Suffix will be added to \_cfwaitingroom.                                                                                                                                                                                                                                    | Ensure your cookie name is compliant. Do not change this often.                                                                                                                        |
| Total active users             | total\_active\_users      | Yes                                     | The maximum number of active sessions allowed in host/path at a given time (must be greater than 200).                                                                                                                                                                                                                        | Set to 75% of origin traffic capacity and adjust as needed. Adjustments may affect estimated wait time shown to end users.                                                             |
| New users per minute           | new\_users\_per\_minute   | Yes                                     | A [threshold](#new-users-per-minute) of users per minute that can be allowed into host/path, greater than 200 and less than or equal to **total active users**.                                                                                                                                                               | Set to 100% of peak traffic to ensure users are only queued when necessary                                                                                                             |
| Session duration               | session\_duration         | No                                      | The amount of time in minutes (between 1 and 30) that a user who left host/path can come [directly back](#session-duration) without having to go into the waiting room. Defaults to 5 minutes.                                                                                                                                |                                                                                                                                                                                        |
| Session Revocation             |                           | No                                      | Revoke a user's session when they perform a specific action by sending a command to the waiting room using an HTTP header on the response from your origin.                                                                                                                                                                   | Enable this setting in the dashboard and add the Cf-Waiting-Room-Command: revoke HTTP header to the response from your origin.                                                         |
| Description                    | description               | No                                      | Description of the waiting room.                                                                                                                                                                                                                                                                                              |                                                                                                                                                                                        |
| Disable session renewal        | disable\_session\_renewal | No                                      | Only available to Enterprise customers with purchase. If true, users only have session duration minutes to browse your site. If false, a user's session cookie is renewed on every request.                                                                                                                                   |                                                                                                                                                                                        |
| JSON response                  | json\_response\_enabled   | No, defaults to false.                  | Send JSON body when receiving an Accept: application/json header, commonly used with native mobile applications.                                                                                                                                                                                                              | Set to true when using a waiting room for non-browser traffic. Follow [this documentation](https://developers.cloudflare.com/waiting-room/how-to/json-response/) for additional steps. |
| Queueing status code           | queueing\_status\_code    | No, defaults 200 (OK).                  | HTTP status code to be returned while a user is queuing.                                                                                                                                                                                                                                                                      |                                                                                                                                                                                        |
| Turnstile Widget Mode          | turnstile\_mode           | Yes, defaults invisible.                | The type of Turnstile widget to use - refer to the [Turnstile documentation](https://developers.cloudflare.com/turnstile/concepts/widget/#widget-modes) for details. Valid values are off, invisible, visible\_non\_interactive, and visible\_managed. Setting this to off will completely disable the Turnstile integration. | Setting this to invisible makes sense for most rooms, unless you would like end users to be aware the challenge is running.                                                            |
| Turnstile Fail Action          | turnstile\_action         | Yes, defaults to log.                   | The action to take when an end user fails a Turnstile challenge. Valid values are log and infinite\_queue.                                                                                                                                                                                                                    | Setting this to log makes sense for most rooms, unless you wish to aggressively block bots using an infinite queue.                                                                    |

## Additional details

### New users per minute

When you configure `new users per minute`, this value **is not** the number of users added per minute.

Instead, it is the threshold of users allowed per minute (less than or equal to the number of `total active users`). You should set this value at 100% of your expected peak traffic to ensure users are only queued when necessary.

### Session duration

Session duration improves user experience in two ways.

First, it prevents visitors from having to pass through a waiting room twice for the same transaction. For example, a visitor might want to make a purchase at `example.com`. There's a lot of traffic at `example.com`, so they queue in the waiting room before entering the online store. After a period of time, they leave the waiting room and enter the online store. They make a purchase and leave the online store.

However, they forgot to add a note to the order or request a receipt. As long as their [session cookie](https://developers.cloudflare.com/waiting-room/reference/waiting-room-cookie/) is still valid (for the length of time specified by the `session duration`), they can re-enter your application without having to re-queue in the waiting room.

Second, session duration lets your waiting room create a dynamic outflow from your application (in addition to dynamic inflow). A user's session cookie expires after a period of inactivity, meaning that new spots can open up as soon as space becomes available and estimated wait times are lower and more accurate.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/reference/configuration-settings/","name":"Configuration settings"}}]}
```

---

---
title: Queueing method
description: Queueing methods including FIFO, random, and passthrough.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Queueing method

The **queueing method** determines the order that visitors exit an active waiting room and reach your application.

Only certain customers can use queue methods besides First In First Out (FIFO). For more details, refer to [Plans](https://developers.cloudflare.com/waiting-room/plans/) page.

Note:

Regardless of the queueing method, if `queueAll` is enabled or an event is prequeueing, users in the waiting room will not be accepted to the origin. These users will always get a waiting room page that refreshes automatically.

## First In First Out (FIFO)

Your waiting room orders visitors according to when they entered the waiting room.

![First In First Out flow showing visitors entering the origin by order of arrival to the waiting room](https://developers.cloudflare.com/_astro/fifo-queueing-method.CkJk7UcN_HRDnR.webp) 

Technically, each user receives a [cookie](https://developers.cloudflare.com/waiting-room/reference/waiting-room-cookie/) that contains a timestamp of when their request first hit an actively queueing waiting room. Cloudflare uses that timestamp to order visitors and provide the estimated wait time.

Use this method when you want to reward visitors who get in the queue first and wait longer.

## Random

When your application has open spots, your waiting room chooses visitors at random to exit the waiting room and enter your application.

![Random queueing flow showing visitors randomly exiting the waiting room and entering an origin](https://developers.cloudflare.com/_astro/random-queueing-method.S1VxQnOu_9YLhG.webp) 

Use this method when you want to distribute products or services more equitably. Earlier users have a better chance of exiting the waiting room before the estimated wait time because they have more chances to be selected.

## Passthrough

Allow all traffic to pass immediately through your waiting room and into your application by setting its `queueing_method` to **passthrough**.

Use this setup when you only want to use your waiting room for events — where you can update the queueing method — and otherwise avoid queueing during low-traffic hours.

Additionally, you can use this queuing method when you want to gather analytics on your traffic but do not want to queue any users. With passthrough on, all traffic will be sent directly to your origin. However, analytics will be gathered on `total active users`, `new users per minute` and `time on origin`. We recommend this as a useful test to gather insights into your traffic patterns to help determine appropriate threshold settings.

## Reject

Prevent any traffic from reaching your application by setting its `queueing_method` to **reject**. Users will get a static page.

Use this setup for event-only endpoints or to perform application maintenance.

## Change queueing methods

Though you can change your [queueing method](https://developers.cloudflare.com/waiting-room/reference/queueing-methods/), it may affect users if your waiting room is actively queueing:

* **From FIFO to Random**: Users will no longer be ordered based on their cookie timestamp, which may affect the displayed wait time.
* **From Random to FIFO**: Users will be ordered based on their cookie timestamp, meaning any new users move to the end of the FIFO queue.

Note

If you change the queueing method from FIFO > Random > FIFO, users will be ordered by their original entry time.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/reference/queueing-methods/","name":"Queueing method"}}]}
```

---

---
title: API commands
description: API commands for managing waiting rooms.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# API commands

Cloudflare Waiting Room redirect visitors to virtual waiting rooms when they are trying to access web pages that have high volumes of traffic.

The [Cloudflare Waiting Room API](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/list/) provides an interface for programmatically managing waiting rooms.

## Request URL format

To invoke a [Cloudflare Waiting Room API](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/list/) operation, append the endpoint to the Cloudflare API base URL:

Terminal window

```

https://api.cloudflare.com/client/v4


```

For authentication instructions, refer to [Getting Started: Requests](https://developers.cloudflare.com/fundamentals/api/) in the Cloudflare API documentation.

For help with endpoints and pagination, refer to [Getting Started: Endpoints](https://developers.cloudflare.com/fundamentals/api/).

## Manage your waiting room

| Operation                                                                                              | Method + URL stub                                             | Notes                              |
| ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------- | ---------------------------------- |
| [List waiting rooms](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/list/)    | GET zones/{:zone\_identifier}/waiting\_rooms                  | List all waiting rooms for a zone. |
| [Create waiting room](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/create/) | POST zones/{:zone\_identifier}/waiting\_rooms                 | Create a waiting room.             |
| [Waiting room details](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/get/)   | GET zones/{:zone\_identifier}/waiting\_rooms/{:identifier}    | Fetch a waiting room.              |
| [Update waiting room](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/update/) | PUT zones/{:zone\_identifier}/waiting\_rooms/{:identifier}    | Update a waiting room.             |
| [Delete waiting room](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/delete/) | DELETE zones/{:zone\_identifier}/waiting\_rooms/{:identifier} | Delete a waiting room.             |
| [Patch waiting room](https://developers.cloudflare.com/api/resources/waiting%5Frooms/methods/edit/)    | PATCH zones/{:zone\_identifier}/waiting\_rooms/{:identifier}  | Patch a configured waiting room.   |

## Fetch the current status of a waiting room

| Operation                                                                                                                                      | Method + URL stub                                                 | Notes                                                                                                                                                                     |
| ---------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Get the current status of a waiting room](https://developers.cloudflare.com/api/resources/waiting%5Frooms/subresources/statuses/methods/get/) | GET zones/{:zone\_identifier}/waiting\_rooms/{:identifier}/status | Returns queueing if the queue is activated (clients are put in the waiting room).Returns not\_queueing if the queue is not activated or if the waiting room is suspended. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/reference/waiting-room-api/","name":"API commands"}}]}
```

---

---
title: Cookies
description: How Waiting Room cookies track visitor sessions.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cookies

A waiting room only uses the `__cfwaitingroom` cookie when a visitor requests access to a host and path combination with an enabled and associated waiting room. When the waiting room is suspended, traffic goes to the origin and the `__cfwaitingroom` cookie is not created. The `__cfwaitingroom` cookie is encrypted to prevent modification by users. You may append a [custom suffix](#customize-cookie-name) to your waiting room cookie to customize the name of your waiting room cookie.

Important:

Cloudflare Waiting Room requires the `__cfwaitingroom` cookie. When a waiting room is actively queueing, users cannot visit that host and path combination without enabling cookies.

## Cookie function

The `__cfwaitingroom` cookie is used to:

* Track a user's position in the waiting room queue and serve them in the correct order.
* Monitor each visitor's duration in the application to provide an [accurate entry time](#estimated-wait-time-fifo-queueing-method) to visitors queueing in the waiting room.
* To allow re-entry for a period of time (specified by [session\_duration](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/#session-duration)) without going back in the waiting room.

## Cookie expiration time

* While a visitor stays in a waiting room, `__cfwaitingroom` cookie expiration is always set to five minutes, but renews every 20 seconds automatically as long as the visitor does not close the tab or leaves your application.
* When the visitor accesses the application, the `__cfwaitingroom` cookie expires after an interval (specified by [session\_duration](https://developers.cloudflare.com/waiting-room/reference/configuration-settings/#session-duration)).

## Customize cookie name

You can customize the name of your waiting room cookie by adding a custom suffix to the end of `__cfwaitingroom`.

To do this via the UI, complete the Custom cookie field in the [Create](https://developers.cloudflare.com/waiting-room/how-to/create-waiting-room/) or [Edit](https://developers.cloudflare.com/waiting-room/how-to/edit-delete-waiting-room/) workflow. To do this via the API, enter a value for `cookie_suffix` when creating or editing a waiting room. The cookie suffix is a required field when [using additional hostnames](https://developers.cloudflare.com/waiting-room/how-to/place-waiting-room/) and paths for a single waiting room. Ensure your cookie is compliant with any applicable policies.

## Estimated wait time (FIFO queueing method)

When a visitor first enters the host and path combination for your waiting room, they receive the `__cfwaitingroom` cookie. That cookie contains a unique group ID, which corresponds to the minute your visitor entered the waiting room. Using this value, we can tell how many visitors are in front of a specific group.

Each cookie also contains a value for `acceptedAt`, which corresponds to the minute your visitor entered your application. This value lets us know how many visitors per minute are leaving the waiting room to enter your application.

```

visitorsAhead ÷ activeUsersToWebApplication = estimatedWaitTime


```

We combine these pieces of information to calculate estimated wait time for each group of visitors.

For more details about the technical implementation of Cloudflare Waiting Room, refer to the [blog post ↗](https://blog.cloudflare.com/building-waiting-room-on-workers-and-durable-objects/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/waiting-room/","name":"Waiting Room"}},{"@type":"ListItem","position":3,"item":{"@id":"/waiting-room/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/waiting-room/reference/waiting-room-cookie/","name":"Cookies"}}]}
```

---

---
title: Cloudflare Web Analytics
description: Privacy-first analytics for your website without changing DNS or using Cloudflare proxy.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare Web Analytics

Get vital web analytics for your website without compromising user privacy.

 Available on all plans 

Cloudflare Web Analytics helps you understand the performance of your web pages as experienced by your site visitors.

---

## Features

###  Filters 

Use filters to refine the data displayed in Web Analytics.

[ Use Filters ](https://developers.cloudflare.com/web-analytics/configuration-options/filters/) 

###  Rules 

Use rules to configure tracking of Web Analytics for specific websites or paths.

[ Use Rules ](https://developers.cloudflare.com/web-analytics/configuration-options/rules) 

###  Dimensions 

Use dimensions to categorize and organize various metrics or data types effectively.

[ Use Dimensions ](https://developers.cloudflare.com/web-analytics/data-metrics/dimensions) 

---

## Related products

**[Analytics](https://developers.cloudflare.com/analytics/)** 

Cloudflare visualizes the metadata collected by our products in the Cloudflare dashboard.

**[Speed](https://developers.cloudflare.com/speed/)** 

Speed allows you to assess the performance of your website and get recommendations of Cloudflare products to enhance the website performance.

---

## More resources

[Resource hub](https://www.cloudflare.com/application-services/products/analytics/) 

Refer to our latest resources to learn more about security, performance and reliability.

[Cloudflare blog](https://blog.cloudflare.com/privacy-first-web-analytics/) 

Read articles about the latest updates about Web Analytics.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web-analytics/","name":"Cloudflare Web Analytics"}}]}
```

---

---
title: About
description: How Cloudflare Web Analytics collects and processes visitor data.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# About

Cloudflare Web Analytics provides free, privacy-first analytics for your website without changing your DNS or using Cloudflare’s proxy. Cloudflare Web Analytics helps you understand the performance of your web pages as experienced by your site visitors.

All you need to enable Cloudflare Web Analytics is a Cloudflare account and a JavaScript snippet on your page to start getting information on page views and visitors. The JavaScript snippet (also known as a beacon) collects metrics using the Performance API, which is available in all major web browsers.

Web Analytics supports Adaptive Bit Rate (ABR). Cloudflare's servers will select the best resolution for each chart or table depending on the size of the data, the date range, your network connection, and other factors. For more information, refer to [Explaining Cloudflare's ABR Analytics ↗](https://blog.cloudflare.com/explaining-cloudflares-abr-analytics/).

The data displayed in Web Analytics is real user monitoring (RUM). For more information, refer to [Real User Monitoring ↗](https://en.wikipedia.org/wiki/Real%5Fuser%5Fmonitoring).

Cloudflare Web Analytics does not collect or use your visitors’ personal data.

[ Get started ](http://dash.cloudflare.com/sign-up/web-analytics) [ Learn more ](https://developers.cloudflare.com/web-analytics/data-metrics/) 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web-analytics/","name":"Cloudflare Web Analytics"}},{"@type":"ListItem","position":3,"item":{"@id":"/web-analytics/about/","name":"About"}}]}
```

---

---
title: Get started
description: Set up Cloudflare Web Analytics for your website.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

## Sites not proxied through Cloudflare

1. In the Cloudflare dashboard, go to the **Web Analytics** page.  
[ Go to **Web analytics** ](https://dash.cloudflare.com/?to=/:account/web-analytics)
2. Select **Add a site**.
3. In **Set up hostname**, write your website's hostname.
4. Select the message box that appears to choose the hostname you have input and select **Done**.
5. Copy the JS snippet from **Manage site**. This is also where you can later edit the hostname you have just added.
6. (Optional) Select **View Analytics sites** to go back on the Web Analytics interface. If you prefer to continue setting up Web Analytics website, continue reading.
7. Add the JS snippet to any of your website’s HTML pages before the ending body tag.

Web analytics is now set up on your website, but it may take a few minutes for Web Analytics data to appear.

Repeat steps 3-7 for all the websites you want to track with Web Analytics by selecting **Add a site** from Web Analytics. In **Web Analytics Sites**, select **Manage site** inside each website's card to adjust Web Analytics for your site at any time.

For more information on how many sites you can track, refer to [Limits](https://developers.cloudflare.com/web-analytics/limits/).

---

## Sites proxied through Cloudflare

1. In the Cloudflare dashboard, go to the **Web Analytics** page.  
[ Go to **Web analytics** ](https://dash.cloudflare.com/?to=/:account/web-analytics)
2. Select **Add a site**.
3. Select a hostname from the drop-down menu > **Done**.

Your website is now using Web Analytics through the automatic setup, which is enabled by default.

You always have the option to go to **Manage Site** and change the automatic setup to one of the following:

* **Enable, excluding visitor data in the EU** \- The JS Snippet will not be injected for visitors from the EU.
* **Enable with JS Snippet installation** \- The JS Snippet needs to be installed manually.
* **Disable** \- The JS Snippet will not be injected and has been disabled.

Repeat these steps for all of the websites you want to track with Web Analytics. Web Analytics is enabled by default for sites proxied through Cloudflare that previously used Browser Insights. Adjust Web Analytics for your site at any time by selecting **Manage site** from Web Analytics.

For more information on how many sites you can track, refer to [Limits](https://developers.cloudflare.com/web-analytics/limits/).

For more information on how to configure which sites or pages you track with Web Analytics, refer to [Rules](https://developers.cloudflare.com/web-analytics/configuration-options/rules/).

Important

If you have a `Cache-Control` header set to `public, no-transform`, Cloudflare proxy will not be able to modify the original payload of the website. Therefore, the Beacon script will not be automatically injected to your site, and Web Analytics will not work. Refer to [Origin cache control](https://developers.cloudflare.com/cache/concepts/cache-control/) for more information.

---

## Pages projects

Cloudflare Pages offers a one-click setup for Web Analytics:

1. In the Cloudflare dashboard, go to the **Workers & Pages** page.  
[ Go to **Workers & Pages** ](https://dash.cloudflare.com/?to=/:account/workers-and-pages)
2. Select your Pages project.
3. Go to **Metrics** and select **Enable** under Web Analytics.

Cloudflare will automatically add the JavaScript snippet to your Pages site on the next deployment.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web-analytics/","name":"Cloudflare Web Analytics"}},{"@type":"ListItem","position":3,"item":{"@id":"/web-analytics/get-started/","name":"Get started"}}]}
```

---

---
title: Notifications
description: Configure notifications for Web Analytics traffic changes.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Notifications

Web Analytics uses Cloudflare's Notification service. When enabled, Web Analytics sends you a weekly report with aggregate visits, page views and median page load time for all your sites, so you can monitor their performance.

  
Refer to [Cloudflare Notifications](https://developers.cloudflare.com/notifications/get-started/) for more information on how to set up an alert.

Weekly summary

**Who is it for?**

Customers using [Web Analytics](https://developers.cloudflare.com/web-analytics/) to monitor their website's performance.

**Other options / filters**

None.

**Included with**

All Cloudflare plans.

**What should you do if you receive one?**

No action is needed. This notification is a weekly summary with reports from your Web Analytics account. Refer to [Notifications](https://dash.cloudflare.com/?to=/:account/notifications) in the Cloudflare dashboard to refine your notifications settings.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web-analytics/","name":"Cloudflare Web Analytics"}},{"@type":"ListItem","position":3,"item":{"@id":"/web-analytics/get-started/","name":"Get started"}},{"@type":"ListItem","position":4,"item":{"@id":"/web-analytics/get-started/notifications/","name":"Notifications"}}]}
```

---

---
title: RUM beacon for Web Analytics
description: Collect real user performance metrics with the RUM beacon.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# RUM beacon for Web Analytics

The RUM beacon is a JavaScript snippet that runs when a Cloudflare customer enables RUM through [Web Analytics](https://developers.cloudflare.com/web-analytics/) or [Observatory](https://developers.cloudflare.com/speed/observatory/). This script runs in users' browsers when they visit the customer's site, and its purpose is to collect performance-related data, for example, page load time, and send it to Cloudflare's systems for processing. This [data](https://developers.cloudflare.com/web-analytics/data-metrics/) is then presented to the customer, providing valuable insights into the website's performance and usage.

The RUM beacon script can be enabled into a webpage in two ways:

* **One-click setup**: For [sites proxied through Cloudflare](https://developers.cloudflare.com/web-analytics/get-started/#sites-proxied-through-cloudflare) that have Web Analytics enabled, the snippet can be _automatically_ injected into pages as the HTML response passes through Cloudflare's edge network to the browser by simply enabling the automatic injection option.
* **Manual setup**: Websites can _manually_ add the script by embedding a code snippet into their pages. Refer to the [Sites not proxied through Cloudflare section](https://developers.cloudflare.com/web-analytics/get-started/#sites-not-proxied-through-cloudflare), for more information about how to manually insert the snippet into your HTML.

## Data collection

Once downloaded to the browser, the RUM beacon script runs as JavaScript in the browser. It collects performance data from browser [APIs ↗](https://developer.mozilla.org/en-US/docs/Web/API/Performance%5FAPI) and sends this data to Cloudflare for processing.

The data collected from the browser is summarized in the table below:

| Field                | Example                                                                                                                | Description                                  | How it is collected                                                                                                                                                                                                                                                                                         |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| pageloadId           | 0c698922-8d60-40bf-85ac-7982b5f8034d                                                                                   | The unique ID for the page.                  | Generated in the browser code.                                                                                                                                                                                                                                                                              |
| referrer             | [https://cfrumtest.com/ ↗](https://cfrumtest.com/)                                                                     | The referring page URL.                      | If it is a multi-page application (MPA), then it is generated from [document.referrer ↗](https://developer.mozilla.org/en-US/docs/Web/API/Document/referrer). If it is a single-page application (SPA), then it is generated from a local in-memory variable in the beacon code which stores previous URLs. |
| startTime            | 1693488419352                                                                                                          | Baseline for performance-related timestamps. | [performance.timeOrigin ↗](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin)                                                                                                                                                                                                         |
| memory               | { totalJSHeapSize: 39973671, usedJSHeapSize: 39127515, jsHeapSizeLimit: 4294705152 }                                   | Measures memory heap size.                   | [performance.memory ↗](https://developer.mozilla.org/en-US/docs/Web/API/Performance/memory) (deprecated)                                                                                                                                                                                                    |
| timings              | Object of [PerformanceTiming ↗](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming)                    | Timing data.                                 | [performance.timing ↗](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timing) (deprecated, fallback when timingV2 is unavailable)                                                                                                                                                             |
| timingV2             | Array of [PerformanceNavigationTiming ↗](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming) | Navigation timing data.                      | [performance.getEntriesByType("navigation") ↗](https://developer.mozilla.org/en-US/docs/Web/API/Performance/getEntriesByType)                                                                                                                                                                               |
| resources            | Array of [PerformanceResourceTiming ↗](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming)     | Resource timing data.                        | [performance.getEntriesByType("resource") ↗](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming)                                                                                                                                                                                    |
| firstPaint           | Array of [PerformancePaintTiming ↗](https://developer.mozilla.org/en-US/docs/Web/API/PerformancePaintTiming)           | Paint timing data.                           | [performance.getEntriesByType("paint") ↗](https://developer.mozilla.org/en-US/docs/Web/API/PerformancePaintTiming)                                                                                                                                                                                          |
| firstContentfulPaint | 209                                                                                                                    | First Contentful Paint metric.               | [web-vitals module ↗](https://www.npmjs.com/package/web-vitals) [1](#user-content-fn-1)                                                                                                                                                                                                                     |
| FCP                  | 209                                                                                                                    | First Contentful Paint metric.               | [web-vitals module ↗](https://www.npmjs.com/package/web-vitals) [1](#user-content-fn-1)                                                                                                                                                                                                                     |
| LCP                  | 209                                                                                                                    | Largest Contentful Paint metric.             | [web-vitals module ↗](https://www.npmjs.com/package/web-vitals) [1](#user-content-fn-1)                                                                                                                                                                                                                     |
| CLS                  | 0.001                                                                                                                  | Cumulative Layout Shift metric.              | [web-vitals module ↗](https://www.npmjs.com/package/web-vitals) [1](#user-content-fn-1)                                                                                                                                                                                                                     |
| TTFB                 | 0.03                                                                                                                   | Time to First Byte metric.                   | [web-vitals module ↗](https://www.npmjs.com/package/web-vitals) [1](#user-content-fn-1)                                                                                                                                                                                                                     |
| INP                  | 1.23                                                                                                                   | Interaction to Next Paint metric.            | [web-vitals module ↗](https://www.npmjs.com/package/web-vitals) [1](#user-content-fn-1)                                                                                                                                                                                                                     |
| landingPath          | [https://cfrumtest.com/ ↗](https://cfrumtest.com/)                                                                     | The landing page URL.                        | [performance.getEntriesByType("navigation") ↗](https://developer.mozilla.org/en-US/docs/Web/API/Performance/getEntriesByType)                                                                                                                                                                               |

## Data processing

RUM data is generally processed at the nearest Cloudflare data center based on how the incoming request is routed. This is determined by a number of factors including [Anycast ↗](https://www.cloudflare.com/en-gb/learning/cdn/glossary/anycast-network/) and [Unimog ↗](https://blog.cloudflare.com/unimog-cloudflares-edge-load-balancer/). Since RUM data does not use location services, it may be processed in a different country or region from where it originated. Although the RUM service receives the client/source IP address from the beacon as part of normal HTTP request handling process, it discards the IP address at the nearest Cloudflare data center and does not store it in core databases or logs.

## Privacy information

The RUM beacon script does not store any data in the browser or access any storage data, such as [cookies ↗](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie), [localStorage ↗](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage), [sessionStorage ↗](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage), IP address, or [IndexedDB ↗](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB%5FAPI/Using%5FIndexedDB). The data we collect is performance data from the browser performance [APIs ↗](https://developer.mozilla.org/en-US/docs/Web/API/Performance%5FAPI). This performance data is ephemeral and only relates to the current webpage that is being viewed. If the user refreshes their browser, all the previous performance data is gone and new performance data starts being available. This data is not stored or accessed from anywhere on the device, it is only available as in-memory data.

## RUM excluding EEA/EU

Customers have the option to enable RUM globally or to limit its application to exclude users connecting to Cloudflare data centers in the EEA/EU. If the latter option is selected, the RUM beacon does not process performance data for users connecting to a Cloudflare data center located in the following countries (ISO codes): AT, BE, BG, HR, CY, CZ, DK, EE, FI, FR, DE, GR, HU, IS, IE, IT, LV, LI, LT, LU, MT, NL, NO, PL, PT, RO, SK, SI, ES, SE, CH, GB.

Free customers have RUM enabled automatically, with EU traffic excluded, and can switch it off if they prefer. Customers on other plans may enable RUM as needed.

![Enable RUM in the dashboard.](https://developers.cloudflare.com/_astro/enable-rum.BsPZ4NVP_Z4ELXQ.webp)

## Footnotes

1. The web-vitals module is an open-source module written by Google. It does not access any type of storage on the browser. [↩](#user-content-fnref-1) [↩2](#user-content-fnref-1-2) [↩3](#user-content-fnref-1-3) [↩4](#user-content-fnref-1-4) [↩5](#user-content-fnref-1-5) [↩6](#user-content-fnref-1-6)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/speed/","name":"Speed"}},{"@type":"ListItem","position":3,"item":{"@id":"/speed/observatory/","name":"Observatory (beta)"}},{"@type":"ListItem","position":4,"item":{"@id":"/speed/observatory/rum-beacon/","name":"RUM beacon for Web Analytics"}}]}
```

---

---
title: Web Analytics for SPAs
description: Configure Web Analytics for single-page applications.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Web Analytics for SPAs

Cloudflare Web Analytics can automatically track user interactions on Single Page Applications (SPAs) by overriding the History API's `pushState` function and listening to the `onpopstate` event. Note that hash-based routers are not supported.

## Disable SPA measurement

If you want to disable the automatic tracking for SPAs, you can do so by adding the `spa` option with a value of `false` in the data attribute of the script tag, as shown below:

```

<script

  defer

  src="https://static.cloudflareinsights.com/beacon.min.js"

  data-cf-beacon=' {"token": "42e216b9090ru59384ygu891dce9eecde", "spa": false} '

></script>


```

### Google Tag Manager (GTM)

If you are using Google Tag Manager (GTM), you can disable SPA tracking by passing the spa option via the query string in the script URL:

```

<script

  defer

  src="https://static.cloudflareinsights.com/beacon.min.js?token=42e216b9090ru59384ygu891dce9eecde&spa=false"

></script>


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web-analytics/","name":"Cloudflare Web Analytics"}},{"@type":"ListItem","position":3,"item":{"@id":"/web-analytics/get-started/","name":"Get started"}},{"@type":"ListItem","position":4,"item":{"@id":"/web-analytics/get-started/web-analytics-spa/","name":"Web Analytics for SPAs"}}]}
```

---

---
title: Limits
description: Rate limits and data retention for Web Analytics.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Limits

Cloudflare limits the number of sites for which you can track web analytics, as well as the number of rules allowed for each plan type. Refer to the following tables for more information.

## Site limits

Cloudflare limits the number of sites for which you can track web analytics when they are not proxied by Cloudflare.

| Site type                      | Limit    |
| ------------------------------ | -------- |
| Not proxied through Cloudflare | 10       |
| Proxied through Cloudflare     | No limit |

## Rules limits

Cloudflare limits the number of Web Analytics rules you can have by plan type. For plans with a limit of zero, Web Analytics injects the JS snippet on all subdomains.

Rules are only available for sites proxied through Cloudflare.

| Plan type  | Rules limit |
| ---------- | ----------- |
| Free       | 0           |
| Pro        | 5           |
| Business   | 20          |
| Enterprise | 100         |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web-analytics/","name":"Cloudflare Web Analytics"}},{"@type":"ListItem","position":3,"item":{"@id":"/web-analytics/limits/","name":"Limits"}}]}
```

---

---
title: FAQs
description: Answers to common questions about Cloudflare Web Analytics.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# FAQs

Below you will find answers to our most commonly asked questions. If you cannot find the answer you are looking for, refer to the [community page ↗](https://community.cloudflare.com/) to explore more resources.

* [Errors](#errors)
* [Setup](#setup)
* [Functionality](#functionality)

## Errors

### When I add the beacon to my website and load the webpage, I see an error that includes `is not allowed by Access-Control-Allow-Origin` (CORS). What is happening?

This error usually occurs when the hostname of the site loading the analytics does not match the name of the analytics site configured in the dashboard. Double-check that they are identical.

Cloudflare matches hostnames based on a postfix. For example, if you set up analytics for `example.com`, we will allow analytics from `www.example.com`, `blog.staging.example.com`, and `fooexample.com`. However, we will not allow analytics from `example.com.br`.

You may also see this error if the site does not send a `Referer` or `Origin` header. The `Referer` header is required (do not try to use the `Referrer-policy` header instead). We have a change in-flight now that only the `Origin` header will be required – we believe there is no way to disable that in the browser.

### The analytics beacon is blocked by ad-blockers (including adblockplus, Brave, DuckDuckGo extension, etc). Why is that?

Cloudflare is aware that the analytics beacon is blocked by these services.

While Cloudflare Web Analytics uses a JavaScript beacon, Cloudflare’s edge analytics cannot be blocked because we can measure every request that is received. Edge analytics are available to any customer who proxies traffic through Cloudflare. Currently, users on Pro, Business, and Enterprise plans get advanced web analytics powered by our edge logs.

### Why am I not seeing all the metrics for single-page application (SPA) or multiple-page application (MPA)?

Every route change that occurs in the single-page app will send the measurement of the route before the route is changed to the beacon endpoint. The measurement for the last route change will be sent whenever the user leaves the tab or closes the browser window. That will trigger `visibilityState` to a hidden state. Whenever that happens, Beacon JS sends the payload using the [Navigator.sendBeacon method ↗](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon) that should not be cancelled even when the browser window is closed. However, due to compatibility, old browsers would fallback to using AJAX (`XmlHttpRequest`), which can be cancelled when the browser window is closed, so the last payload that gets sent to the beacon endpoint can be lost. Also, due to various network conditions, there can be data loss when the payload is sent to the beacon endpoint.

### For the same site, why would I see more data reported with an automatic setup?

Unless you are using Rules to control which pages to be measured, using [automatic setup](https://developers.cloudflare.com/web-analytics/get-started/#sites-proxied-through-cloudflare) will inject the JS snippet on all pages (sub-domains) under the zone.

If you used a [manual setup](https://developers.cloudflare.com/web-analytics/get-started/#sites-not-proxied-through-cloudflare) instead, only those pages that render the JS snippet will be reported.

Note

Since only one JS snippet can be rendered and used per page, you cannot have multiple snippets on the same page.

### My website is proxied through Cloudflare, but Web Analytic's automatic setup is not working.

If you have a `Cache-Control` header set to `public, no-transform`, Cloudflare proxy will not be able to modify the original payload of the website. Therefore, the Beacon script will not be automatically injected to your site, and Web Analytics will not work. Refer to [Origin cache control](https://developers.cloudflare.com/cache/concepts/cache-control/) for more information.

### Why am I getting a `405 Method Not Allowed` error from `/cdn-cgi/rum`?

The `/cdn-cgi/rum` endpoint only accepts `POST` requests for data ingestion. If you send a request using any other HTTP method (for example, `GET`, `PUT`, or `DELETE`), the endpoint returns a `405 Method Not Allowed` response with an `Allow: POST, OPTIONS` header (`OPTIONS` is allowed for [CORS ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS) support).

The Web Analytics beacon (`beacon.min.js`) always uses `POST` when reporting metrics. If you see `405` errors in your logs, the requests are not coming from the beacon itself.

They are most likely coming from an automated testing tool making erroneous requests, in which case you should correct it to use `POST` or ignore the errors.

We do not support custom integrations directly with the endpoint: all requests should originate from our beacon JavaScript.

---

## Setup

### I am proxying my site through Cloudflare. Should I manually add the JS beacon?

You can, but you do not have to. Cloudflare Web Analytics is designed primarily for customers who do not use Cloudflare's proxy to measure their web traffic.

Existing Cloudflare customers can access analytics collected from our edge on the **Analytics** tab of the dashboard. You can also enable Web Analytics to measure performance using JavaScript.

Using a domain proxied through Cloudflare with [automatic setup](https://developers.cloudflare.com/web-analytics/get-started/#sites-proxied-through-cloudflare) will report stats back to your own domain's `/cdn-cgi/rum` endpoint. If you have installed JS snippet yourself (a [manual setup](https://developers.cloudflare.com/web-analytics/get-started/#sites-not-proxied-through-cloudflare)), it will report back to `cloudflareinsights.com/cdn-cgi/rum` endpoint.

### Can I add Web Analytics to my site using a tag manager like Google Tag Manager (GTM)?

Yes. Instead of embedding the script using a tag manager as shown here:

```

<script

  defer

  src="https://static.cloudflareinsights.com/beacon.min.js"

  data-cf-beacon='{"token": "$SITE_TOKEN"}'

></script>


```

Add the following script:

```

<script

  defer

  src="https://static.cloudflareinsights.com/beacon.min.js?token=$SITE_TOKEN"

></script>


```

### What do I need to add to my Content Security Policy (CSP)?

If your site implements a Content Security Policy (CSP), you'll need to add some entries to this HTTP header to allow browsers to download the beacon script and transmit beacons to Cloudflare.

**Warning:** be sure to validate any CSP changes on a test environment before releasing an update to your production environment. You may wish to use [Content Security Rules ↗](https://developers.cloudflare.com/client-side-security/rules/) or trial with `Content-Security-Policy-Report-Only` first.

You'll first need to permit our script to execute by adding it to your `script-src` directive:

```

script-src [...existing values...] https://static.cloudflareinsights.com/beacon.min.js


```

_Note: if you have a query string in the script as per the example above for Google Tag Manager, then you'll need to include this in the URL too, e.g. `script-src [...existing values...] https://static.cloudflareinsights.com/beacon.min.js?token=$SITETOKEN`_

Secondly, you'll need to permit the endpoint we transmit the beacon data to.

For automatic injection, this will be the same domain, so ensure your `connect-src` includes `'self'`:

```

connect-src [...existing values...] 'self'


```

For manual embedding, this script instead connects to `cloudflareinsights.com`, so ensure that's included instead:

```

connect-src [...existing values...] cloudflareinsights.com


```

### How can I enforce Subresource Integrity (SRI) with the JS beacon?

If you're using the automated injection (i.e. not the manually-embedded script approach mentioned above), Cloudflare automatically includes an `integrity` attribute in the `<script>`. This ensures the script will only execute if a local hash of its downloaded contents match the integrity hash supplied in the HTML.

Unfortunately, if you're using the manually-embedded script approach, there is no current way to safely apply an `integrity` attribute because we do not support version-pinning our beacon script. We do this because it ensures we can release periodic updates to maintain security, address bugs and ensure

### Can I use the same JS Snippet for a different domain?

No. However, if the apex domain (also known as "root domain" or "naked domain") is the same, you can use the same site tag. For example, if you have provided us a hostname `example.com` when registering a site, you can use the JS snippet from that site for `abc.example.com` and `def.example.com` since they use the same apex domain. When payload gets sent to the beacon endpoint, we validate the hostname with postfix matching, so if your domain shares the same apex domain, that would work.

### Can I use automatic setup with a DNS-only domain (CNAME setup)?

No, you can only use the [automatic setup](https://developers.cloudflare.com/web-analytics/get-started/#sites-proxied-through-cloudflare) with JS snippet injection if traffic to your domain is proxied through Cloudflare (orange-clouded).

If you have a DNS-only domain, you will have to do a [manual setup](https://developers.cloudflare.com/web-analytics/get-started/#sites-not-proxied-through-cloudflare) instead.

### What prevents the JS Snippet from being added to a page?

For Cloudflare to automatically add the JavaScript snippet, your pages need to have valid HTML.

For example, Cloudflare would not be able to enable Web Analytics on a page like this:

index.html

```

Hello world.


```

For Web Analytics to correctly insert the JavaScript snippet, you would need valid HTML output, such as:

index.html

```

<!DOCTYPE html>

<html>

  <head>

    <title>Title</title>

  </head>

  <body>


    <p>Hello world.</p>


  </body>

</html>


```

### Can I use Real User Monitoring (RUM) with Cloudflare Workers?

Cloudflare's Real User Monitoring (RUM) operates exclusively on the initial client request and cannot collect metrics from Worker subrequests. This is a fundamental architectural limitation designed to ensure accurate performance measurements and prevent duplicate or misleading analytics data.

---

## Functionality

### Is the data sampled?

We retain unsampled beacon data for the past 7 days, after this point data is aggregated down to around 10%.

When aggregating metrics in the Cloudflare Dashboard or querying the GraphQL API, a level of sampling (between 0.0001% and 100%) will be dynamically selected based on the filters applied and the volume of matching rows. This ensures a high confidence in the accuracy of figures while maintaining a reasonable response time. You can [read more about this approach on the Cloudflare blog ↗](https://blog.cloudflare.com/explaining-cloudflares-abr-analytics/).

Note: the GraphQL API exposes a `sampleInterval` field to indicate which level of sampling has been applied to the query.

* The beacon script will fire on every pageview.
* The data ingestion pipeline does not apply sampling—every received beacon will be recorded.
* We store the unsampled data for 7 days.
* We also aggregate it down so it's around 10% of the original volume for long-term storage.
* Sites with very low traffic volumes are sampled to greater percentages to maintain high confidence in aggregate figures.

### Can I see server-side analytics by URL?

Web Analytics only displays client-side analytics. All Cloudflare customers who proxy their traffic also get analytics based on traffic at their edge.

Currently, users on Pro, Business, and Enterprise plans get advanced HTTP traffic analytics, which is the only way to see features like a breakdown of traffic by URL based on server-side analytics.

### What is the period of time I can access data in Web Analytics?

Currently, you can access data for the previous six months.

### Does Cloudflare Web Analytics support UTM parameters?

Not yet. UTM parameters are special query string parameters that can help track where traffic is coming from. Currently, Cloudflare Web Analytics do not log query strings to avoid collecting potentially sensitive data, but we may add support for this in the future.

### Does Web Analytics support custom events?

Not yet, but we may add support for this in the future.

### Can I track more than one website with Web Analytics?

Yes. Right now there is a soft limit of ten sites per account, but that can be adjusted by contacting Cloudflare support.

### When does the beacon send metrics to the `/cdn-cgi/rum/` endpoint?

For traditional websites, not Single Page Applications (SPAs), the Web Analytics beacon reports to the `/cdn-cgi/rum/` endpoint when the page has finished loading (load event) and when the user leaves the page. For Single Page Applications, additional metrics are sent for every route change to capture the page load event.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web-analytics/","name":"Cloudflare Web Analytics"}},{"@type":"ListItem","position":3,"item":{"@id":"/web-analytics/faq/","name":"FAQs"}}]}
```

---

---
title: Changelog
description: Track the latest updates and changes to Web Analytics features.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Changelog

Cloudflare occasionally updates the `beacon.min.js` file to improve Web Analytics functionality. The table below includes a log of what changed in the `beacon.min.js` file and when.

[ Subscribe to RSS ](https://developers.cloudflare.com/web-analytics/changelog/index.xml)

## 2026-05-15

Updated Google's web-vitals library to version 4.2.4 and captured Interaction to Next Paint (INP) sub-part metrics (Input Delay, Processing Duration, Presentation Delay)

## 2024-06-11

Enhanced to include reporting of Server-Timing headers.

## 2024-05-22

Introducing new metric fields, transferSize and decodedBodySize are included.

## 2024-04-17

Introducing new metric fields, deliveryType (dt) and navigationType (nt) are included.

## 2023-10-18

Manages A/B testing tags.

## 2023-07-25

Fixed ETag format in the response header.

## 2023-07-13

Fixed the issue that was causing an illegal invocation error.

## 2023-04-19

Reports additional LCP diagnostic information using web-vitals library's attribution build.

## 2023-04-06

Updated webpack configuration to output code in ECMAScript 3 (ES3) format.

## 2023-03-23

Updated Google's web-vitals library (version 3.1.1) and removed experimental `server-timing` header.

## 2022-10-17

Updated to report new metrics such as time to first byte (TTFB), interaction to next paint (INP), and first contentful paint (FCP). Additionally, it reports `navigator.webdriver`, `server-timing` header (experimental), and protocol info (`nextHopProtocol`).

## 2021-12-14

Improved site filtering.

## 2021-11-16

When using the automatic installation feature of the JavaScript Beacon (available only to customers proxied through Cloudflare - also known as orange-clouded customers),[Subresource Integrity (SRI)](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource%5FIntegrity) is now enabled by default. SRI is a security feature that enables browsers to verify that resources they fetch are delivered without unexpected manipulation.

## 2021-09-01

Improved to report debugging information for Core Web Vitals.

## 2021-05-28

`startsWith` function replaced with `indexOf` function, which prevents rendering if multiple beacon scripts are loaded.

## 2021-05-12

Reporting endpoint changed from `/cdn-cgi/beacon/performance` to `/cdn-cgi/rum` (for Browser Insights only).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web-analytics/","name":"Cloudflare Web Analytics"}},{"@type":"ListItem","position":3,"item":{"@id":"/web-analytics/changelog/","name":"Changelog"}}]}
```

---

---
title: Filters
description: Learn how to use filters in Cloudflare Web Analytics.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Filters

To filter the data shown on Web Analytics:

1. In the Cloudflare dashboard, go to the **Web Analytics** page.  
[ Go to **Web analytics** ](https://dash.cloudflare.com/?to=/:account/web-analytics)
2. Select the website you want to check.
3. Select **Add filter**.
4. In the **New filter** box, choose your criteria from the dropdown. Refer to the [Dimensions](https://developers.cloudflare.com/web-analytics/data-metrics/dimensions/) page for a list of available filters and their descriptions.
5. Select **Apply**.

### Additional tips

* By default, Web Analytics shows data for the previous 24 hours. Adjust the time range using the dropdown menu above the graph.
* Select and drag the cursor on the graph to choose a custom time period.
* Scroll below the graph to view detailed breakdowns, for instance of top visits by country or by device type.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web-analytics/","name":"Cloudflare Web Analytics"}},{"@type":"ListItem","position":3,"item":{"@id":"/web-analytics/configuration-options/","name":"Configuration options"}},{"@type":"ListItem","position":4,"item":{"@id":"/web-analytics/configuration-options/filters/","name":"Filters"}}]}
```

---

---
title: Rules
description: Create rules to include or exclude traffic from Web Analytics.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Rules

Use **Rules** to configure whether to track Web Analytics for specific websites or paths. By default, Web Analytics automatically creates a single rule for the zone that injects the JavaScript (JS) snippet for all pages.

Rules are only available for sites proxied through Cloudflare. For more information, refer to [Limits](https://developers.cloudflare.com/web-analytics/limits/).

1. In the Cloudflare dashboard, go to the **Web Analytics** page.  
[ Go to **Web analytics** ](https://dash.cloudflare.com/?to=/:account/web-analytics)
2. Find the site you want to configure and select **Manage site**.
3. Select **Advanced options** \> **Add rule**.
4. Select the **Action** and fill in the hostname and path(s) you want to add a rule for.
5. If you want to add additional rules, select **Add rule**. Otherwise select **Update** to save the rule.

Warning

Configuration rules have precedence over any Web Analytics rules. If a Web Analytics rule turns on analytics measurements for an incoming request and the same request matches a configuration rule turning off Web Analytics, the configuration rule will win.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web-analytics/","name":"Cloudflare Web Analytics"}},{"@type":"ListItem","position":3,"item":{"@id":"/web-analytics/configuration-options/","name":"Configuration options"}},{"@type":"ListItem","position":4,"item":{"@id":"/web-analytics/configuration-options/rules/","name":"Rules"}}]}
```

---

---
title: Core Web Vitals
description: View Core Web Vitals metrics collected by Web Analytics.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Core Web Vitals

[Core Web Vitals ↗](https://www.cloudflare.com/learning/performance/what-are-core-web-vitals/) are high-level metrics designed by Google to capture the user experience. Three core Web Vitals metrics are measured: Largest Contentful Paint, First Input Delay, and Cumulative Layout Shift. Each of these metrics is automatically assigned a rating of Good, Needs Improvement, or Poor based on the industry standard methodology and testing designed by Google. Page load time statistics are supplemented by First Paint and First Contentful Paint.

Note

Core Web Vitals is currently only supported in Chromium browsers, with Safari and Firefox coming soon.

## Access Core Web Vitals

Core Web Vitals enables you to easily pinpoint which elements in a web page are affecting the user's experience while browsing your website, in a visual form. To access Core Web Vitals:

1. In the Cloudflare dashboard, go to the **Web Analytics** page.  
[ Go to **Web analytics** ](https://dash.cloudflare.com/?to=/:account/web-analytics)
2. Select your website and select **Core Web Vitals**.

### Core Web Vitals metrics

Core Web Vitals is divided into three main sections, each one with information about a specific feature that affects user experience:

* [Largest Contentful Paint (LCP) ↗](https://web.dev/optimize-lcp/): Measures perceived load speed by the user. It returns how long the main content of the page takes to be loaded.
* [Interaction to Next Paint (INP) ↗](https://web.dev/inp/): Measures user interface responsiveness – how quickly a website responds to user interactions like clicks or key presses.
* [Cumulative Layout Shift (CLS) ↗](https://web.dev/optimize-cls/): Measures visual stability, that is, if there are shifts in the page layout as the various elements are being loaded into view.

Each of these metrics represents an impact to the user experience, which is quantified and graded by Web Analytics.

Cloudflare Web Analytics offers interactive exploration in Core Web Vitals by allowing you to filter data by URL, Browser, Operating System, Country, and Element.

### Debug view

Below each graph, the Debug View section has the top five elements with a negative impact on each metric. Selecting the elements shown in the data table gives you more details about them.

Each table — LCP, INP, and CLS — also shows you the performance of these elements in the 75th percentile (P75) at a glance. Selecting in each row of the table lets you expand the element and have access to more information, including P50, P90 and P99 metrics.

These numbers refer to how an element performs relatively to others in your page. For example, if an element takes 3,900 ms to load and is in the 75 percentile, this means that it is slower to load than 75% of the elements in your page.

![Debug View page](https://developers.cloudflare.com/_astro/core-web-vitals-debug-view.BXtLIgXn_Z1Tx4a4.webp) 

## Information collected

Web Analytics uses its lightweight JavaScript beacon to collect the information Vitals Explorer uses. It does not use any client-side state, such as cookies or `localStorage`, to collect usage metrics. Vitals Explorer also does not fingerprint individuals via their IP address, User Agent string, or any other data.

### Common data collected for all Core Web Vitals metrics

#### Element

A CSS selector representing the DOM node. With this string, you can use `document.querySelector(<element_name>)` in the dev console of your browser to find out which DOM node has a negative impact on your scores/values.

#### Path

The URL path at the time the Core Web Vitals are captured.

#### Value

[The metric value ↗](https://web.dev/cls/#layout-shift-score) for each Core Web Vitals. This value is in milliseconds for LCP or NIP and a score for CLS.

### Additional data collected for Largest Contentful Paint

#### URL

The source URL (such as image, text, web fonts).

#### Size

The source object's size in bytes.

### Additional data collected for Cumulative Layout Shift

Layout information is a JSON value that includes width, height, x axis position, y axis position, left, right, top, and bottom. These values represent the layout shifts that happen on the page.

#### CurrentRect

Captures the layout information of the DOM element with the largest area, after the shift in the page has occurred. This JSON value is shown as **Current** in the **Debug View** section. To access it, scroll to the **Cumulative Layout Shifts (CLS)** graphic > **Debug View**. Select any element from that table to access the **Layout Shifts** section, where **Current** is presented.

#### PreviousRect

Captures the layout information of the DOM element with the largest area, before the shift in the page has occurred. This JSON value is shown as **Previous** in the **Debug View** section. To access it, scroll to the **Cumulative Layout Shifts (CLS)** graphic > **Debug View**. Select any element from that table to access the **Layout Shifts** section, where **Previous** is presented.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web-analytics/","name":"Cloudflare Web Analytics"}},{"@type":"ListItem","position":3,"item":{"@id":"/web-analytics/data-metrics/","name":"Data and metrics"}},{"@type":"ListItem","position":4,"item":{"@id":"/web-analytics/data-metrics/core-web-vitals/","name":"Core Web Vitals"}}]}
```

---

---
title: Data origin and collection
description: How Web Analytics collects data from visitor browsers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Data origin and collection

Web Analytics relies on the `performance.getEntriesByType('navigation')` object to collect metrics about page load performance. If Navigation Timing Level 2 is not supported, then [performance.timing (Level 1) ↗](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timing) is used.

Refer to the [W3C Processing Model ↗](https://www.w3.org/TR/navigation-timing-2/#processing-model) for a visual depiction of the sequence of timing events for web page loads.

## Data collection and reporting

Web Analytics collects the minimum amount of information - timing metrics - to show customers how their websites perform. Cloudflare does not track individual end users across our customers’ Internet properties.

The Web Analytics performance beacon loads from `https://static.cloudflareinsights.com/beacon.min.js`. You may need to update your [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) settings to load this script.

Beacon data is sent to `https://<yourdomainname>/cdn-cgi/rum` for sites proxied through Cloudflare or `https://cloudflareinsights.com/cdn-cgi/rum` for sites not proxied through Cloudflare. Core Web Vital metrics are reported when the `visibilityState` is hidden for the first time after the page load event is triggered.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web-analytics/","name":"Cloudflare Web Analytics"}},{"@type":"ListItem","position":3,"item":{"@id":"/web-analytics/data-metrics/","name":"Data and metrics"}},{"@type":"ListItem","position":4,"item":{"@id":"/web-analytics/data-metrics/data-origin-and-collection/","name":"Data origin and collection"}}]}
```

---

---
title: Dimensions
description: Dimensions available for filtering and grouping Web Analytics data.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Dimensions

Dimensions are the labels used to describe different types of metrics or data. For example, **Referer** is the data collected from external links referring visits to a page, while **Browser** shows which browsers accessed your website.

Below you can find a list of the different dimensions you can use to filter Web Analytics:

* **Country**: The visitor's country.
* **Host**: The domain of the site's URL.
* **Path**: The links within your site referring visits to a page.
* **Referer**: The external links referring visits to a page. You can access `referer host` data on the dashboard. Additionally, you can access data for the `referer path` from the GraphQL API.
* **Device type**: The device visitors use to access a page (for example, desktop, mobile, or tablet).
* **Browser**: The web browser (for example, Chrome, Safari) visitors use to access your website.
* **Operating system**: The operating system visitors use to access a page.
* **Site**: The website's domain name. Used for high-level segmentation of data. For example, you can use it for a particular zone or gray-clouded website.
* **Exclude Bots**: Exclude bot traffic from the dataset. With this dimension set to `Yes`, the resulting dataset will be a closer representation of real user traffic.
* **Navigation type**: Which method was used to load the HTML document. Refer to [Navigation types](#navigation-types) for a breakdown.
![Web Analytics dimensions page](https://developers.cloudflare.com/_astro/dash-web_analytics-dimensions.DqK_-eil_Z1zFiTJ.webp) 

## Navigation types

| Type                    | Cache hit? | Explanation                                                                                                                                                                                                                                                                                                                                                  |
| ----------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Navigate                | ❌          | The visitor clicked a link or submitted a form but the document was either not found or stale in the browsers HTTP cache, so a network request was made to load the document.                                                                                                                                                                                |
| Navigate Cache          | ✅          | The visitor clicked a link or submitted a form and the document was found and fresh within the browsers HTTP cache, so no network request was necessary for the document.                                                                                                                                                                                    |
| Navigate Prefetch Cache | ✅          | The visitor clicked a link or submitted a form and the document has been prefetched into the browsers HTTP cache, so no network request was necessary for the document.                                                                                                                                                                                      |
| Prerender               | ✅          | The visitor clicked a link or submitted a form but the browser had already prerendered the page, so no network request was necessary for the document.                                                                                                                                                                                                       |
| Reload                  | ❌          | The visitor reloaded the page but the document was either not found or stale in the browsers HTTP cache, so a network request was made to load the document.                                                                                                                                                                                                 |
| Reload Cache            | ✅          | The visitor reloaded the page and the document was found and fresh within the browsers HTTP cache, so no network request was necessary for the document.                                                                                                                                                                                                     |
| Back-forward            | ❌          | The visitor used the back/forward buttons/gestures in their browser but the previously-loaded document either not found or stale in the browsers HTTP cache OR a feature was used which prevents using the cache (refer to the explanation in [Back/forward cache ↗](https://web.dev/articles/bfcache)), so a network request was made to load the document. |
| Back-forward Cache      | ✅          | The visitor used the back/forward buttons/gestures in their browser and the document was found and fresh within the browsers HTTP cache, so no network request was necessary for the document.                                                                                                                                                               |
| Restore                 | ✅          | The browser was able to restore this page, for example when a tab has been paused due to inactivity.                                                                                                                                                                                                                                                         |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web-analytics/","name":"Cloudflare Web Analytics"}},{"@type":"ListItem","position":3,"item":{"@id":"/web-analytics/data-metrics/","name":"Data and metrics"}},{"@type":"ListItem","position":4,"item":{"@id":"/web-analytics/data-metrics/dimensions/","name":"Dimensions"}}]}
```

---

---
title: High-level metrics
description: Page views, visits, and other high-level metrics in Web Analytics.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# High-level metrics

Understanding the key metrics in web analytics is essential for optimizing your website’s performance and user experience. Here are the high-level metrics tracked by Cloudflare Web Analytics:

* **Visits** \- A page view that originated from a different website or direct link. Cloudflare checks where the HTTP referer does not match the hostname. One visit can consist of multiple page views.
* **Page views** \- A successful HTTP response with a content-type of HTML.
* **Page load time** \- The total amount of time required to load the page.
* **[Core Web Vitals ↗](https://www.cloudflare.com/learning/performance/what-are-core-web-vitals/)** \- Higher-level metrics designed by Google to capture the user experience more completely.
![Web Analytics overview page](https://developers.cloudflare.com/_astro/dash-web_analytics-overview.Z0JtJyOL_5dwhM.webp) 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web-analytics/","name":"Cloudflare Web Analytics"}},{"@type":"ListItem","position":3,"item":{"@id":"/web-analytics/data-metrics/","name":"Data and metrics"}},{"@type":"ListItem","position":4,"item":{"@id":"/web-analytics/data-metrics/high-level-metrics/","name":"High-level metrics"}}]}
```

---

---
title: Page load time
description: Page load time metrics collected by Web Analytics.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Page load time

Page load time summary gives you an overview of how long your web page takes to load, broken down by area. To access Page load time:

1. Go to [Web Analytics ↗](https://dash.cloudflare.com/?to=/:account/web-analytics) from your account home page, and choose a website.
2. Select **Page load time**.

## Components

Below is a list of all the components you can inspect:

### Page load

The total amount of time required to load the page. Note that page load time does not correspond to the sum of the other timings available in Web Analytics. This happens because the page load time also includes timings that are not displayed, such as pre-DNS lookup timings and unattributed gaps between timing metrics.

### DNS (`domainLookupEnd` \- `domainLookupStart`)

How long a DNS query takes. This could appear as zero for reused connections or content stored in the local cache (memory or disk).

### TCP (`connectEnd` \- `connectStart`)

How long it takes to establish a TCP connection with the server. If using HTTPS, this process includes TLS negotiation time.

### Request (`responseStart` \- `requestStart`)

The time elapsed between making an HTTP request and receiving the first byte of the response.

### Response (`responseEnd` \- `responseStart`)

The time elapsed between the first byte and the last byte of the received response. Think of this as a resource download time.

### Processing (`domComplete` \- `domInteractive`)

How long it took to render the page. This includes loading any resources that block page rendering, including images, scripts, and style sheets. If this number is big, optimize your document architecture, resource size, or configure settings in the Cloudflare Speed app. This document process can be drilled down more with `domInteractive`, `domContentLoadedEventStart`, `domContentLoadedEventEnd`, and `domComplete`.

### Load Event (`loadEventEnd` \- `loadEventStart`)

An event triggered by the browser when a document and its resources finish loading. The Load Event duration may be a useful metric if you have additional functions or any logic for the load event.

![Web Analytics load time summary page](https://developers.cloudflare.com/_astro/dash-web_analytics-page_load_time.CrUXAPNx_Z1RQArK.webp) 

## Data collected for Paint Timings

To make Web Analytics work, Cloudflare collects several types of data points. These are the additional data points collected for Paint Timings:

### First Paint

The time between navigation and when the browser renders the first pixels to the screen.

### First Contentful Paint

Time when the browser renders the first bit of content from the DOM.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web-analytics/","name":"Cloudflare Web Analytics"}},{"@type":"ListItem","position":3,"item":{"@id":"/web-analytics/data-metrics/","name":"Data and metrics"}},{"@type":"ListItem","position":4,"item":{"@id":"/web-analytics/data-metrics/page-load-time-summary/","name":"Page load time"}}]}
```

---

---
title: Web3
description: Cloudflare offers gateways to various networks to help Web3 developers do what they do best, develop applications without having to worry about running infrastructure.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Web3

Develop Web3 applications without having to worry about running infrastructure

 Add-on feature 

Web3 (also called the distributed web) refers to a set of technologies for hosting content and applications on decentralized networks — where data is stored across many computers rather than on a single server. These networks use consensus protocols to agree on the state of shared data without relying on a central authority.

Note

Enterprise customers can preview this product as a [non-contract service](https://developers.cloudflare.com/billing/understand/preview-services/), which provides full access, free of metered usage fees, limits, and certain other restrictions.

---

## Features

###  IPFS Gateway 

 Paid add-on 

Provides a read-only, HTTP-accessible interface to the [Interplanetary File System (IPFS)](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/ipfs/).

[ Use IPFS Gateway ](https://developers.cloudflare.com/web3/ipfs-gateway/) 

###  Ethereum Gateway 

 Paid add-on 

Gives you read and write access to the [Ethereum network](https://developers.cloudflare.com/web3/ethereum-gateway/concepts/ethereum/) without installing any software on your computer.

[ Use Ethereum Gateway ](https://developers.cloudflare.com/web3/ethereum-gateway/) 

---

## Benefits

Cloudflare's Web3 gateways provide HTTP-accessible interfaces to Web3 networks. Instead of running your own IPFS or Ethereum node, you access these networks through Cloudflare, which provides:

* **Ease of access**: Access content from Web3 networks without installing or running any special software.
* **Security**: Get the protection benefits of Cloudflare's global anycast network for [enhanced security ↗](https://blog.cloudflare.com/cloudflare-thwarts-17-2m-rps-ddos-attack-the-largest-ever-reported/).
* **Reduced maintenance**: Cloudflare — not your developers — maintains and monitors the gateway infrastructure.
* **Reliability**: Cloudflare's global anycast network provides a high level of [reliability and availability ↗](https://www.cloudflare.com/network/).
* **Performance**: With data centers in [hundreds of cities worldwide ↗](https://www.cloudflare.com/network/), responses are cached and served from locations close to your end users.

---

## More resources

[Plans](https://www.cloudflare.com/plans/#overview) 

Compare available Cloudflare plans

[Pricing](https://dash.cloudflare.com/?to=/:account/:zone/web3/) 

Explore pricing options for Web3 Gateways in the dashboard

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}}]}
```

---

---
title: About
description: How Cloudflare Web3 gateways connect HTTP clients to decentralized networks.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# About

Cloudflare Web3 gateways let your application interact with decentralized networks (IPFS and Ethereum) using standard HTTP requests. Instead of running your own IPFS or Ethereum node, you point your domain at Cloudflare and the gateway handles network communication on your behalf.

When you [create a gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/#create-a-gateway), Cloudflare automatically creates and adds specific [DNS records](https://developers.cloudflare.com/web3/reference/gateway-dns-records/) to your Cloudflare account. When the hostname associated with your gateway receives requests, its DNS records route these requests to a Cloudflare Workers script that communicates with the underlying network.

![Cloudflare's Web3 gateways provide HTTP-accessible interfaces to the IPFS and Ethereum networks. For more details, continue reading.](https://developers.cloudflare.com/_astro/web3-gateway-flow-diagram.C8S74hHM_261bFb.webp) 

## Read operations

When your application sends a read request (for example, fetching a file from IPFS or querying an Ethereum account balance), the gateway checks whether the response is already cached at a nearby Cloudflare data center.

* If cached, the gateway returns the content immediately over HTTP, without contacting the underlying network.
* If not cached, the gateway fetches the content from Cloudflare's own IPFS or Ethereum nodes, caches it for future requests, and returns it over HTTP.

## Write operations

Note

Only available for gateways to EVM-based chains, such as [Ethereum](https://developers.cloudflare.com/web3/how-to/use-ethereum-gateway).

Write operations submit new data to the network. For example, sending a transaction or deploying a smart contract. The gateway forwards your request to one of Cloudflare's Ethereum nodes, which places the transaction in its mempool (a queue of pending transactions waiting to be included in a block).

From there, the network's validators select transactions from the mempool, group them into a block, and reach consensus on the block's validity. Once the block is accepted, it becomes part of the permanent blockchain record. The gateway returns a transaction ID so your application can track the result.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/about/","name":"About"}}]}
```

---

---
title: Get started
description: Set up a Cloudflare Web3 gateway for Ethereum or IPFS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

Use this tutorial to set up a Cloudflare Web3 gateway, which gives your application HTTP access to the IPFS or Ethereum network without running your own node.

## Before you begin

Before you start, make sure you have [set up an account](https://developers.cloudflare.com/fundamentals/account/) and [added your website](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) to Cloudflare.

## Step 1 - Subscribe to a gateway

Web3 gateways are a paid add-on. To get access, [subscribe to a gateway](https://developers.cloudflare.com/web3/how-to/enable-gateways/).

## Step 2 - Create a gateway

After purchasing a gateway subscription, create a gateway.

Create via dashboard

To create a gateway using the dashboard:

1. In the Cloudflare dashboard, go to the **Web3** page.  
[ Go to **Web3** ](https://dash.cloudflare.com/?to=/:account/:zone/web3)
2. Click **Create Gateway**.
3. Enter the following information:
* **Hostname**: Enter a hostname to use as your gateway, which has to be a subdomain of the current Cloudflare zone.
* **Gateway Description**: Enter a description to help distinguish between different gateways.
* **Gateway Type**: Select a gateway target of [IPFS DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/), [IPFS Universal Path](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/universal-gateway/), or [Ethereum](https://developers.cloudflare.com/web3/ethereum-gateway/).
* **DNSLink**: Only applicable to IPFS gateways, more details at [DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/#how-is-it-used-with-cloudflare).
1. Click **Deploy**.

Create via API

To create a gateway using the API, send a [POST](https://developers.cloudflare.com/api/resources/web3/subresources/hostnames/methods/create/) request that includes the following parameters:

* `name`: The hostname that will point to the target gateway via a `CNAME` record.
* `target`: The gateway target for the hostname (`ethereum`, `ipfs`, `ipfs_universal_path`).

If you need help with API authentication, refer to [Cloudflare API documentation](https://developers.cloudflare.com/fundamentals/api/).

Request

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/web3/hostnames" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data '{

  "name": "gateway.example.com",

  "description": "This is my IPFS gateway.",

  "target": "ipfs",

  "dnslink": "/ipns/onboarding.ipfs.cloudflare.com"

}'


```

The response contains the complete definition of the new gateway.

Response

```

{

  "success": true,

  "errors": [],

  "messages": [],

  "result": {

    "id": "<WEB3_GATEWAY_ID>",

    "name": "gateway.example.com",

    "description": "This is my IPFS gateway.",

    "status": "active",

    "target": "ipfs",

    "dnslink": "/ipns/onboarding.ipfs.cloudflare.com",

    "created_on": "<CREATED_ON_DATE>",

    "modified_on": "<MODIFIED_ON_DATE>"

  }

}


```

When you create a gateway, Cloudflare automatically:

* Creates and adds [records to your Cloudflare DNS](https://developers.cloudflare.com/web3/reference/gateway-dns-records/) so your gateway can receive and route traffic appropriately.
* [Proxies](https://developers.cloudflare.com/dns/proxy-status/) traffic to that hostname.
* Issues an SSL/TLS certificate to cover the specified hostname.

## Step 3 - Customize Cloudflare settings

Once your gateway becomes [active](https://developers.cloudflare.com/web3/reference/gateway-status/), you can customize the Cloudflare settings associated with your hostname.

Since your traffic is automatically proxied through Cloudflare, you customize your website settings to take advantage of various [security, performance, and reliability](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/#cloudflare-as-a-reverse-proxy) benefits.

## Step 4 - Restrict gateway access (optional)

If you are using your gateway for backend services, you may want to use Cloudflare Zero Trust to [restrict gateway access](https://developers.cloudflare.com/web3/how-to/restrict-gateway-access/).

## Step 5 - Set up usage notifications

Since this is a service with [usage-based billing](https://developers.cloudflare.com/billing/understand/usage-based-billing/), Cloudflare recommends that you set up usage-based billing notifications to avoid unexpected bills.

To set up those notifications:

1. In the Cloudflare dashboard, go to the **Notifications** page.  
[ Go to **Notifications** ](https://dash.cloudflare.com/?to=/:account/notifications)
2. On **Alert Type** of **Usage Based Billing**, click **Select**.
3. Fill out the following information:  
   * **Name**  
   * **Product**  
   * **Notification limit** (exact metric will vary based on product)  
   * **Notification email**  
Note  
Some plans also have access to alerts through [PagerDuty](https://developers.cloudflare.com/notifications/get-started/configure-pagerduty/) and [Webhooks](https://developers.cloudflare.com/notifications/get-started/configure-webhooks/).
4. Select **Save**.

## Step 6 - Use the gateway

Once you have created a gateway and updated your Cloudflare settings, you can start using your [IPFS](https://developers.cloudflare.com/web3/how-to/use-ipfs-gateway/) or [Ethereum](https://developers.cloudflare.com/web3/how-to/use-ethereum-gateway/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/get-started/","name":"Get started"}}]}
```

---

---
title: IPFS Gateway
description: Serve IPFS content through Cloudflare without running an IPFS node.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# IPFS Gateway

Cloudflare's IPFS gateway provides a read-only, HTTP-accessible interface to the [Interplanetary File System (IPFS)](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/ipfs/). This gateway does not require you to download any special software or give up any storage space on your computer.

* [ Concepts ](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/)
* [ Reference ](https://developers.cloudflare.com/web3/ipfs-gateway/reference/)
* [ Troubleshooting ](https://developers.cloudflare.com/web3/ipfs-gateway/troubleshooting/)

## Availability

| Free                                         | Pro                                                                              | Business                                                                         | Enterprise                                                                       |                                                                                                                                                                                       |
| -------------------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Availability                                 | Yes (Usage-based billing)                                                        | Yes (Usage-based billing)                                                        | Yes (Usage-based billing)                                                        | Yes (Usage-based billing)                                                                                                                                                             |
| Total gateways                               | 15                                                                               | 15                                                                               | 15                                                                               | Unlimited                                                                                                                                                                             |
| Gateway types                                | [DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/) | [DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/) | [DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/) | [DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/),[Universal Gateway](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/universal-gateway/) |
| Included bandwidth (without additional cost) | 50 GB data transfer                                                              | 50 GB data transfer                                                              | 50 GB data transfer                                                              | 100 GB data transfer                                                                                                                                                                  |
| File size limit                              | None                                                                             | None                                                                             | None                                                                             | None                                                                                                                                                                                  |

Note

For more pricing details, refer to the [Web3 product page ↗](https://www.cloudflare.com/application-services/products/web3/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/ipfs-gateway/","name":"IPFS Gateway"}}]}
```

---

---
title: DNSLink gateways
description: Use DNSLink to map domain names to IPFS content.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# DNSLink gateways

When you set up a gateway with a DNSLink record, that gateway is restricted to a particular piece of content — either a specific Content Identifier (CID) or an Interplanetary Name Service (IPNS) hostname. This is called a restricted gateway.

A restricted gateway differs from a [universal gateway](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/universal-gateway/), which allows users to access any content hosted on the IPFS network.

## What is DNSLink?

Every file on [IPFS](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/ipfs/) is identified by a [CID ↗](https://docs.ipfs.io/concepts/glossary/#cid) — a long string like `bafybeiaysi4s6lnjev27ln5icwm6tueaw2vdykrtjkwiphwekaywqhcjze`. These CIDs are not practical for end users to type or remember, the same way IP addresses (`192.0.2.1`) are not practical compared to domain names (`example.com`).

DNSLink solves this by mapping a human-readable domain name to an IPFS CID through a DNS TXT record. You put your website files into an IPFS directory and create a DNSLink record pointing your domain to that directory's CID. Users then access your site through a readable URL like `https://cf-ipfs.com/ipns/en.wikipedia-on-ipfs.org/`, and the gateway resolves it to the correct CID.

DNSLink also simplifies content updates. When you publish a new version of your site, update the DNSLink record to point to the new CID and the gateway serves the new version automatically — no need to share a new URL.

Note

For additional details, refer to the official [IPFS documentation ↗](https://docs.ipfs.tech/concepts/dnslink/).

## How is it used with Cloudflare?

You have the option to specify the DNSLink when you [create an IPFS gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/#create-a-gateway), which serves as a custom hostname that directs users to a website already hosted on IPFS.

By default, your DNSLink path is `/ipns/onboarding.ipfs.cloudflare.com`. If you choose to put your website in a different content folder hosted at your own IPFS node or with a pinning service, you will need to specify that value.

For example, the default DNSLink record for `www.example.com` would look like this:

| Record type | Name                      | Content                                      |
| ----------- | ------------------------- | -------------------------------------------- |
| TXT         | \_dnslink.www.example.com | dnslink=/ipns/onboarding.ipfs.cloudflare.com |

For more details about the DNS records created by the IPFS gateway, refer to [Gateway DNS records](https://developers.cloudflare.com/web3/reference/gateway-dns-records/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/ipfs-gateway/","name":"IPFS Gateway"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/ipfs-gateway/concepts/","name":"Concepts"}},{"@type":"ListItem","position":5,"item":{"@id":"/web3/ipfs-gateway/concepts/dnslink/","name":"DNSLink gateways"}}]}
```

---

---
title: Interplanetary File System (IPFS)
description: How the InterPlanetary File System stores and retrieves content.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Interplanetary File System (IPFS)

The Interplanetary File System (IPFS) is a peer-to-peer file storage network. Instead of storing files on a single server (the way traditional web hosting works), IPFS distributes files across many computers around the world.

Any computer can join the IPFS network by installing the IPFS software and start hosting and serving files.

If someone uploads a file to the IPFS network, anyone else running IPFS can view and download that file — no central server is involved.

## Content Identifiers

Every file added to IPFS is given a unique address derived from a hash of the file's content. This address is called a Content Identifier (CID). A CID contains two pieces of information: the hash of the file and an identifier for the hash algorithm used, combined into a single string.

Because the CID is derived from the content itself, two identical files always produce the same CID, and any change to a file produces a different CID. This is what makes IPFS "content-addressed" — you look up files by what they contain, not by where they are stored.

IPFS uses [SHA-256 ↗](https://en.wikipedia.org/wiki/SHA-2) by default, and encodes the result with [Base58 ↗](https://en.wikipedia.org/wiki/Base58) — an encoding scheme that omits visually ambiguous characters (such as zero and the capital letter O) to reduce transcription errors.

A CID typically looks like: `QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco`

IPFS also supports other encodings ([Base32 ↗](https://en.wikipedia.org/wiki/Base32)) and hash algorithms ([SHA-3 ↗](https://en.wikipedia.org/wiki/SHA-3), [BLAKE2 ↗](https://en.wikipedia.org/wiki/BLAKE%5F%28hash%5Ffunction%29)).

## Uploading to IPFS

IPFS tracks which computers have which files using a [Distributed Hash Table (DHT) ↗](https://en.wikipedia.org/wiki/Distributed%5Fhash%5Ftable) — a lookup system that maps CIDs to the network addresses of computers hosting that content. No single computer holds the entire lookup table. Instead, each computer in the network stores a portion of it and knows where to find the rest.

"Uploading" content to IPFS does not mean sending your file to a central server. It means announcing to the network that you have the content by adding an entry to the DHT that maps your file's CID to your network address. When someone else wants to download that file, they look up the CID in the DHT, find your address, and download the data directly from you.

Because multiple computers can host the same file, downloads are spread across all of them. If any one host goes offline, the others continue to serve the content. This redundancy is what gives IPFS its speed and reliability advantages over single-server hosting.

## Directories

You can upload more than just individual files. For example, consider a folder called `example`, which has exactly one file, `example_text.txt`, containing the string `I'm trying out IPFS`.

If that folder were uploaded with the command `ipfs add -r ./example`, both the folder and the file it contains would have their own CID. In this case, the folder would have the CID `QmdbaSQbGU6Wo9i5LyWWVLuU8g6WrYpWh2K4Li4QuuE8Fr` while the file would have the CID `QmXnnyufdzAWL5CqZ2RnSNgPbvCc1ALT73s6epPrRnZ1Xy`.

You could then access the file in two ways:

* Requesting the file directly:  
`https://cloudflare-ipfs.com/ipfs/QmXnnyufdzAWL5CqZ2RnSNgPbvCc1ALT73s6epPrRnZ1Xy`
* Requesting the file by name, from the directory:  
`https://cloudflare-ipfs.com/ipfs/QmdbaSQbGU6Wo9i5LyWWVLuU8g6WrYpWh2K4Li4QuuE8Fr/example_text.txt`

While the CID of a file will only change if the file itself changes, the CID of a directory changes any time **any** of the files in it change, or if any files are added/removed.

Directories make it possible to address an entire static website with a single CID and access different pages of the website by requesting different files in the directory.

## Related resources

For help with additional concepts, refer to the [IPFS ↗](https://docs.ipfs.tech/concepts/) documentation.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/ipfs-gateway/","name":"IPFS Gateway"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/ipfs-gateway/concepts/","name":"Concepts"}},{"@type":"ListItem","position":5,"item":{"@id":"/web3/ipfs-gateway/concepts/ipfs/","name":"Interplanetary File System (IPFS)"}}]}
```

---

---
title: Universal Path gateway
description: Access any IPFS content through the Universal Path gateway.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Universal Path gateway

A Universal Path gateway is a gateway without a DNSLink record. It allows users to access any content hosted on the IPFS network by specifying a CID or IPNS path in the URL.

This differs from a [restricted gateway](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/), which limits the gateway to a single piece of content (a specific CID or IPNS hostname).

## How is it used with Cloudflare?

You can set up a Universal Path gateway the same way you [create any gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/).

Because a Universal Path gateway is open by default, you may want to use the [gateway blocklist](https://developers.cloudflare.com/web3/how-to/manage-gateways/#update-blocklist) to prevent access to specific content. You can block one or more:

* CIDs (`QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB`)
* IPFS content paths (`/ipfs/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG/readme`)
* IPNS content paths (`/ipns/example.com`)

Note

This feature is limited to specific plans. For more detail, refer to [Limits](https://developers.cloudflare.com/web3/reference/limits/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/ipfs-gateway/","name":"IPFS Gateway"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/ipfs-gateway/concepts/","name":"Concepts"}},{"@type":"ListItem","position":5,"item":{"@id":"/web3/ipfs-gateway/concepts/universal-gateway/","name":"Universal Path gateway"}}]}
```

---

---
title: Automated deployments
description: Automate IPFS content deployment with CI/CD pipelines.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Automated deployments

Static sites are easy to deploy automatically. The code of the site is usually kept in a Git repository and deployed by pushing the latest commit to a repository that's connected to a Continuous Integration service like [Travis CI ↗](https://travis-ci.org/), or by pushing to a repository directly on the server and activating a post-receive hook. Either way, the production version of the site is built and then copied into the serving path of an Apache or NGINX instance.

IPFS usually fits into these systems: instead of copying the production version of a website into the serving path of an HTTP server, you would upload the same files to an IPFS node and update your DNS records with the new hash. There are several tools that help with different parts of this:

* [ipfs-deploy ↗](https://github.com/agentofuser/ipfs-deploy) helps upload data to a third-party pinning providers and automatically update Cloudflare-managed DNS records.
* [dnslink-cloudflare ↗](https://github.com/ipfs-shipyard/dnslink-cloudflare) is a script to programmatically update DNSLink records. This can be run with the `-Q` flag of `ipfs add` that only outputs the top-level hash.
* [Fission's IPFS support ↗](https://guide.fission.codes/developers/custom-domains/using-cloudflare-ipfs-gateway) lets you use the Fission IPFS app publishing system from the CLI or from GitHub Actions, while using Cloudflare-managed DNS and gateway.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/ipfs-gateway/","name":"IPFS Gateway"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/ipfs-gateway/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/web3/ipfs-gateway/reference/automated-deployment/","name":"Automated deployments"}}]}
```

---

---
title: Peering
description: Peer with IPFS content providers for faster content delivery.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Peering

If you are running an IPFS node that serves many requests - like a public HTTP gateway - you may be able to speed up queries by maintaining long-lived connections to nodes that provide a large volume of data.

This process is known as **Peering** and you can tell IPFS to prioritize Cloudflare's peers by editing the Peering configuration in your IPFS config file.

```

{

  "Peering": {

    "Peers": [

      {

        "ID": "QmcFf2FH3CEgTNHeMRGhN7HNHU1EXAxoEk6EFuSyXCsvRE",

        "Addrs": [

          "/dnsaddr/node-1.ingress.cloudflare-ipfs.com"

        ]

      },

      {

        "ID": "QmcFmLd5ySfk2WZuJ1mfSWLDjdmHZq7rSAua4GoeSQfs1z",

        "Addrs": [

          "/dnsaddr/node-2.ingress.cloudflare-ipfs.com"

        ]

      },

      {

        "ID": "QmcfFmzSDVbwexQ9Au2pt5YEXHK5xajwgaU6PpkbLWerMa",

        "Addrs": [

          "/dnsaddr/node-3.ingress.cloudflare-ipfs.com"

        ]

      },

      {

        "ID": "QmcfJeB3Js1FG7T8YaZATEiaHqNKVdQfybYYkbT1knUswx",

        "Addrs": [

          "/dnsaddr/node-4.ingress.cloudflare-ipfs.com"

        ]

      },

      {

        "ID": "QmcfVvzK4tMdFmpJjEKDUoqRgP4W9FnmJoziYX5GXJJ8eZ",

        "Addrs": [

          "/dnsaddr/node-5.ingress.cloudflare-ipfs.com"

        ]

      },

      {

        "ID": "QmcfZD3VKrUxyP9BbyUnZDpbqDnT7cQ4WjPP8TRLXaoE7G",

        "Addrs": [

          "/dnsaddr/node-6.ingress.cloudflare-ipfs.com"

        ]

      },

      {

        "ID": "QmcfZP2LuW4jxviTeG8fi28qjnZScACb8PEgHAc17ZEri3",

        "Addrs": [

          "/dnsaddr/node-7.ingress.cloudflare-ipfs.com"

        ]

      },

      {

        "ID": "QmcfgsJsMtx6qJb74akCw1M24X1zFwgGo11h1cuhwQjtJP",

        "Addrs": [

          "/dnsaddr/node-8.ingress.cloudflare-ipfs.com"

        ]

      },

      {

        "ID": "Qmcfr2FC7pFzJbTSDfYaSy1J8Uuy8ccGLeLyqJCKJvTHMi",

        "Addrs": [

          "/dnsaddr/node-9.ingress.cloudflare-ipfs.com"

        ]

      },

      {

        "ID": "QmcfR3V5YAtHBzxVACWCzXTt26SyEkxdwhGJ6875A8BuWx",

        "Addrs": [

          "/dnsaddr/node-10.ingress.cloudflare-ipfs.com"

        ]

      },

      {

        "ID": "Qmcfuo1TM9uUiJp6dTbm915Rf1aTqm3a3dnmCdDQLHgvL5",

        "Addrs": [

          "/dnsaddr/node-11.ingress.cloudflare-ipfs.com"

        ]

      },

      {

        "ID": "QmcfV2sg9zaq7UUHVCGuSvT2M2rnLBAPsiE79vVyK3Cuev",

        "Addrs": [

          "/dnsaddr/node-12.ingress.cloudflare-ipfs.com"

        ]

      }

    ]

  }

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/ipfs-gateway/","name":"IPFS Gateway"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/ipfs-gateway/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/web3/ipfs-gateway/reference/peering-with-content-providers/","name":"Peering"}}]}
```

---

---
title: Using IPFS with your website
description: Host your website on IPFS and serve it through Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Using IPFS with your website

Though it is not required, it is strongly recommended that websites hosted on IPFS use only relative links, unless linking to a different domain. This is because data can be accessed in many different (but ultimately equivalent) ways:

* From your custom domain: `https://ipfs.tech/index.html`
* From a gateway: `https://cloudflare-ipfs.com/ipns/ipfs.tech/index.html`
* By immutable hash: `https://cloudflare-ipfs.com/ipfs/QmNksJqvwHzNtAtYZVqFZFfdCVciY4ojTU2oFZQSFG9U7B/index.html`

Using only relative links within a web application supports all of these at once, and gives the most flexibility to the user. The exact method for switching to relative links, if you do not use them already, depends on the framework you use.

## Angular, React, Vue

These popular JavaScript frameworks are covered in a [blog post ↗](https://medium.com/pinata/how-to-easily-host-a-website-on-ipfs-9d842b5d6a01) from [Pinata ↗](https://pinata.cloud/). They are fixed with minor config changes.

## Gatsby

Gatsby is a JavaScript framework based on React. There is a [plugin ↗](https://www.gatsbyjs.org/packages/gatsby-plugin-ipfs/) for it that ensures links are relative.

## Jekyll

Add a file `_includes/base.html` with the contents:

```

{% assign base = '' %}

{% assign depth = page.url | split: '/' | size | minus: 1 %}

{% if    depth <= 1 %}{% assign base = '.' %}

{% elsif depth == 2 %}{% assign base = '..' %}

{% elsif depth == 3 %}{% assign base = '../..' %}

{% elsif depth == 4 %}{% assign base = '../../..' %}{% endif %}


```

This snippet computes the relative path back to the root of the website from the current page. Update any pages that need to link to the root by adding this at the top:

```

{%- include base.html -%}


```

This snippet also prefixing any links with `{{base}}`. So for example, we would change`href="https://developers.cloudflare.com/css/main.css"` to be `href="https://developers.cloudflare.com/web3/ipfs-gateway/reference/updating-for-ipfs/%7B%7Bbase%7D%7D/css/main.css"`

## Generic

For other frameworks, or if a framework was not used, there's a script called [make-relative ↗](https://github.com/tmcw/make-relative) that will parse the HTML of a website and automatically rewrite links and images to be relative.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/ipfs-gateway/","name":"IPFS Gateway"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/ipfs-gateway/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/web3/ipfs-gateway/reference/updating-for-ipfs/","name":"Using IPFS with your website"}}]}
```

---

---
title: Troubleshooting
description: Resolve common IPFS Gateway issues including 523 and 524 errors.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

## Cloudflare-specific

### No link named "ipfs"

If you get a `no link named "ipfs" under <<CID>>` error message when trying to access content through Cloudflare's IPFS gateway, that means you have created a gateway without a value for the [DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink).

Since Cloudflare currently only supports restricted gateways - and not [universal gateways](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/universal-gateway/) \- these requests will continue to fail until you specify a DNSLink value.

### Check Cloudflare's status

It is worth checking for recent incidents on Cloudflare's [status dashboard ↗](https://www.cloudflarestatus.com/) that may have affected our gateway, but the best place to get up-to-date information about issues facing IPFS is the [IPFS Discussion Forum ↗](https://discuss.ipfs.io/).

## Generic IPFS

IPFS is still a developing protocol and content is often unavailable or slow to load for reasons outside of Cloudflare's control. Usually, this happens for one of the following reasons.

### The content was uploaded to a free/anonymous pinning service.

Free and anonymous pinning services can often be used to get content on IPFS in a pinch, but they'll often stop pinning content soon after it's uploaded. Running your own server or using a pinning service are the recommended alternatives, and will keep your content online more reliably.

### No node with the requested content is online.

Content will only stay on the IPFS network as long as there's at least one node that's serving it. If all of the nodes that were serving a given piece of content go offline, the content will be inaccessible until one of them comes back online.

### The nodes with the requested content are not publicly addressable.

It's common for people who run an IPFS node on their home Wi-Fi to have very long wait times or a high rate of request failure. This is because the rest of the nodes in the IPFS network have difficulty connecting to them through their NAT (Internet router). This can be solved by setting up Port Forwarding on the router, to direct external connections to port 4001 to the host with the IPFS node, or by moving the node to a hosted server/VM.

### The nodes with the requested content are not pinning it.

If several minutes have passed since files were uploaded to an IPFS node and they're still not discoverable by other gateways, it's possible the node is having trouble announcing the files to the rest of the network. You can make sure the node with the content has pinned it by running:

```

ipfs pin -r <content id>


```

And you can force the actual announcement by running:

```

ipfs dht provide -rv <content id>


```

The second command will run indefinitely and has quite complicated output, so you may want to run it in the background and omit the `-v` flag.

### The nodes with the requested content are too old.

IPFS issues mandatory updates from time to time that introduce breaking protocol changes. Cloudflare tries to say ahead of these updates and may, as a result, lose connectivity with older nodes.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/ipfs-gateway/","name":"IPFS Gateway"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/ipfs-gateway/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: Ethereum Gateway
description: Access the Ethereum network through Cloudflare without running a node.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Ethereum Gateway

Cloudflare's Ethereum Gateway gives you read and write access to the [Ethereum network](https://developers.cloudflare.com/web3/ethereum-gateway/concepts/ethereum/) without installing any software on your computer.

In particular, users can read all information that has been agreed upon by the consensus of existing nodes in the network. In addition, they can write their own transactions and smart contracts to be stored by these nodes in a distributed manner. Anyone else on the network will be able to view these transactions, and even run your smart contracts using their own supply of the Ethereum currency.

These interactions take place through the official [Ethereum JSON-RPC API ↗](https://github.com/ethereum/execution-apis) and use [Cloudflare-supported API methods](https://developers.cloudflare.com/web3/ethereum-gateway/reference/supported-api-methods/).

## Availability

| Free                                          | Pro                       | Business                  | Enterprise                |                           |
| --------------------------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- |
| Availability                                  | Yes (Usage-based billing) | Yes (Usage-based billing) | Yes (Usage-based billing) | Yes (Usage-based billing) |
| Total gateways                                | 15                        | 15                        | 15                        | Unlimited                 |
| Included bandwidth  (without additional cost) | 500,000 HTTP requests     | 500,000 HTTP requests     | 500,000 HTTP requests     | 1,000,000 HTTP requests   |

Note

For more pricing details, refer to the [Web3 product page ↗](https://www.cloudflare.com/application-services/products/web3/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/ethereum-gateway/","name":"Ethereum Gateway"}}]}
```

---

---
title: Ethereum network
description: How the Ethereum blockchain and smart contracts work.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Ethereum network

The Ethereum network is a decentralized platform for running programs called smart contracts. A smart contract is a program stored at a unique address on the network that executes automatically when triggered by a transaction. Because smart contracts run on Ethereum, they can handle any computation that a general-purpose programming language can express.

When a smart contract runs, every node in the network independently verifies the result. The network then reaches consensus — all nodes agree on the outcome — and the result becomes part of the permanent record.

## Smart contracts

Running a smart contract requires paying a fee in Ethereum's currency, ETH. This fee (called "gas") compensates the network's validators for the computational work of executing your transaction and adding it to the blockchain.

If the smart contract transfers ETH between accounts, those balance changes are also recorded in the blockchain. The blockchain therefore represents a complete, verifiable record of the network's current state — including every account balance and every smart contract's stored data.

## Addressing

Transactions are grouped into blocks, and blocks are chained together in sequence to form the blockchain — a complete history of every transaction since the network started.

Each block has a unique hash identifier (a long hexadecimal string like `0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3q`), and each transaction within a block has its own hash as well. You can use either hash to look up and inspect specific blocks or transactions.

When a new block is added, it is broadcast to every node in the network. Because all transactions are public and verifiable, the blockchain provides a transparent and accountable record of the network's state.

## Read and write content

To read data from Ethereum — such as checking account balances or querying smart contract state — you need access to an Ethereum node. You can run a node yourself (for example, using [go-ethereum ↗](https://github.com/ethereum/go-ethereum/)) or use a gateway like Cloudflare's. Reads are performed through the [JSON-RPC API ↗](https://github.com/ethereum/wiki/wiki/JSON-RPC), a standard interface for sending queries to the network.

To write data — such as sending a transaction or deploying a smart contract — you also use the JSON-RPC API, but you must additionally provide ETH to pay for the transaction fee and sign the transaction with the private key from your [Ethereum wallet ↗](https://www.ethereum.org/use/#%5F3-what-is-a-wallet-and-which-one-should-i-use). Once submitted, the transaction is broadcast to the network and included in the blockchain.

## Connect your website to the gateway

To access the Ethereum network from a custom domain name — without running your own node — you can [create an Ethereum Gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/#create-a-gateway) through Cloudflare.

## Related resources

If you’re interested in learning more, you can read the official [RPC documentation ↗](https://github.com/ethereum/wiki/wiki/JSON-RPC), along with the official documentation [provided by Ethereum ↗](https://www.ethereum.org/use/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/ethereum-gateway/","name":"Ethereum Gateway"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/ethereum-gateway/concepts/","name":"Concepts"}},{"@type":"ListItem","position":5,"item":{"@id":"/web3/ethereum-gateway/concepts/ethereum/","name":"Ethereum network"}}]}
```

---

---
title: Node types
description: Full nodes, archive nodes, and their role in Ethereum queries.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Node types

Ethereum nodes are the computers that store blockchain data and process queries. There are three types, each with different trade-offs between storage requirements and query capabilities.

## Full nodes

Full nodes store the current state of the blockchain and validate new blocks as they are produced. Once fully synced with the network, a full node can answer queries about any current blockchain data. Full nodes do not retain every historical state — they can recalculate past states when needed, but this requires additional computation.

## Light nodes

Light nodes store only block headers (summaries of each block) rather than the full blockchain state. They can query the Ethereum network but rely on full nodes to provide and verify the underlying data. This makes them much smaller and faster to set up, but less self-sufficient.

## Archive nodes

Archive nodes are full nodes that also store every historical state of the blockchain. Because they keep this data readily available in local storage, they can answer queries about past states (such as "what was this account's balance at block 5,000,000?") much faster than a full node, which would need to recalculate that state.

## Nodes at Cloudflare

Cloudflare's Ethereum Gateway provides access to full and archive nodes.

The archive nodes serve requests for the following [RPC state methods ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#state%5Fmethods) when the block number parameter is before the most recent 128 blocks or the default block parameter is set to `earliest`:

* [eth\_getBalance ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetbalance)
* [eth\_getCode ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetcode)
* [eth\_getTransactionCount ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgettransactioncount)
* [eth\_getStorageAt ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetstorageat)
* [eth\_call ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fcall)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/ethereum-gateway/","name":"Ethereum Gateway"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/ethereum-gateway/concepts/","name":"Concepts"}},{"@type":"ListItem","position":5,"item":{"@id":"/web3/ethereum-gateway/concepts/node-types/","name":"Node types"}}]}
```

---

---
title: Kill Switches
description: Disable Ethereum Gateway features in an emergency.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Kill Switches

When writing contracts, be especially careful to write secure code and include a kill switch to ensure that if any bugs do reside in the code, they can be squashed. If you do not include a kill switch and there are vulnerabilities in the smart contract that can be exploited, this can lead to the theft of resources from the smart contract or from other individuals.

This was brought into sharp focus during the [infamous DAO incident ↗](https://en.wikipedia.org/wiki/The%5FDAO%5F%28organization%29). The DAO smart contract acted as a complex, decentralized venture capital fund and held Ether worth $250 million at its peak collected from a group of investors. Hackers exploited vulnerabilities in the smart contract, stealing $50 million worth of Ether.

Because there is no way to undo transactions in Ether, there was a highly controversial “hard fork," where the majority of the community agreed to accept a block that contained an _irregular state change_ that essentially drained all DAO funds into a special “WithdrawDAO” recovery contract. By convincing enough miners to accept this irregular block as valid, the DAO was able to return investors funds. However, not everyone agreed with the chain, with those who disagreed rejecting the irregular block and forming the Ethereum Classic network, each blockchain grew independently.

## Limitations

Kill switches can cause their own problems. Like if a contract that is a library has its kill switch flipped. All contracts relying on this contract can't operate as intended even though the underlying library code is immutable. Recently, an attacker triggered a kill switch in an underlying library function that caused over 500,000 Ether to get [stuck in multi-signature wallets ↗](https://www.parity.io/security-alert-2/). Users of the multi-signature library assumed the immutability of the code meant that the library would always operate as anticipated, and accepted the block. In the wake of this, there are many tools that check smart contracts for bugs or enable bug bounties.

> Smart contracts interacting with the blockchain are only deterministic when accounting for the state of the blockchain.

## How is this different?

This is a radically different approach for providing transparency and accountability. Because all contracts and transactions are public and verified by **consensus**, trust is distributed amongst the people, rather than centralized in a few big institutions.

The trust given to institutions is historic. This history builds trustworthiness.

The trust placed in consensus-based algorithms is based on the assumption that most people are honest, or more accurately that no sufficiently large subset of people can be made to collude to produce a malicious outcome. This is the_democratisation of trust_. In the DAO attack, a majority of nodes agreed to accept an irregular state transition. This effectively undid the damage of the attack, and shows how, at least in the world of blockchain, perception is reality. Because most people “believed" -- accepted this irregular block, it became a “real” -- valid block.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/ethereum-gateway/","name":"Ethereum Gateway"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/ethereum-gateway/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/web3/ethereum-gateway/reference/kill-switches/","name":"Kill Switches"}}]}
```

---

---
title: Rinkeby deprecation
description: Deprecation notice for the Rinkeby test network.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Rinkeby deprecation

Though Cloudflare's Ethereum Gateway launched with support for the Rinkeby testnet, Rinkeby did not run through [The Merge ↗](https://ethereum.org/en/upgrades/merge/) and - as a result - will no longer be a reliable staging environment for mainnet.

Cloudflare will be deprecating support for Rinkeby on January 30, 2023.

## Migration

To avoid any issues with your Web3 development or debugging, you should switch over to the [Sepolia testnet](https://developers.cloudflare.com/web3/ethereum-gateway/reference/supported-networks/), which is fully supported with your Ethereum Gateway.

To migrate, you should update the endpoints you use when [reading from or writing to](https://developers.cloudflare.com/web3/how-to/use-ethereum-gateway/) the Ethereum network.

For example, you might have been using the previous endpoints to interact with your Ethereum Gateway.

Previous curl

```

curl https://web3-trial.cloudflare-eth.com/v1/rinkeby \

--header 'Content-Type: application/json' \

--data '{

  "jsonrpc": "2.0",

  "method": "eth_getBlockByNumber",

  "params": ["0x2244", true],

  "id": 1

}'


```

Previous JS Fetch API

```

await fetch(

  new Request('https://web3-trial.cloudflare-eth.com/v1/rinkeby', {

    method: 'POST',

    body: JSON.stringify({

      jsonrpc: '2.0',

      method: 'eth_getBlockByNumber',

      params: ['0x2244', true],

      id: 1,

    }),

    headers: {

      'Content-Type': 'application/json',

    },

  })

).then(resp => {

  return resp.json();

});


```

To migrate away from Rinkeby, change the end of your endpoint to use another testnet.

New curl

```

curl https://web3-trial.cloudflare-eth.com/v1/sepolia \

--header 'Content-Type: application/json' \

--data '{

  "jsonrpc": "2.0",

  "method": "eth_getBlockByNumber",

  "params": ["0x2244", true],

  "id": 1

}'


```

New JS Fetch API

```

await fetch(

  new Request('https://web3-trial.cloudflare-eth.com/v1/sepolia', {

    method: 'POST',

    body: JSON.stringify({

      jsonrpc: '2.0',

      method: 'eth_getBlockByNumber',

      params: ['0x2244', true],

      id: 1,

    }),

    headers: {

      'Content-Type': 'application/json',

    },

  })

).then(resp => {

  return resp.json();

});


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/ethereum-gateway/","name":"Ethereum Gateway"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/ethereum-gateway/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/web3/ethereum-gateway/reference/rinkeby-deprecation/","name":"Rinkeby deprecation"}}]}
```

---

---
title: Supported API methods
description: Ethereum JSON-RPC methods supported by the Cloudflare gateway.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Supported API methods

The full list of API methods that are supported by an Ethereum Gateway is given below. The gateway returns a `403` if a method is specified that is not supported.

For a full list of JSON-RPC API methods, refer to the [JSON-RPC specification ↗](https://github.com/ethereum/execution-apis).

| JSON-RPC method                                                                                                                                | Cloudflare Ethereum Gateway support |
| ---------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- |
| [web3\_clientVersion ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#web3%5Fclientversion)                                           | ✅                                   |
| [web3\_sha3 ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#web3%5Fsha3)                                                             | ✅                                   |
| [net\_version ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#net%5Fversion)                                                         | ✅                                   |
| [net\_listening ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#net%5Flistening)                                                     | ✅                                   |
| [eth\_syncing ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fsyncing)                                                         | ✅                                   |
| [eth\_mining ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fmining)                                                           | ✅                                   |
| [eth\_gasPrice ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgasprice)                                                       | ✅                                   |
| [eth\_feeHistory ↗](https://github.com/ethereum/execution-apis)[1](#user-content-fn-2)                                                         | ✅                                   |
| [eth\_blockNumber ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fblocknumber)                                                 | ✅                                   |
| [eth\_chainId ↗](https://github.com/ethereum/execution-apis)                                                                                   | ✅                                   |
| [eth\_getBalance ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetbalance)                                                   | ✅                                   |
| [eth\_getStorageAt ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetstorageat)                                               | ✅                                   |
| [eth\_getTransactionCount ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgettransactioncount)                                 | ✅                                   |
| [eth\_getBlockTransactionCountByHash ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetblocktransactioncountbyhash)           | ✅                                   |
| [eth\_getBlockTransactionCountByNumber ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetblocktransactioncountbynumber)       | ✅                                   |
| [eth\_getUncleCountByBlockHash ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetunclecountbyblockhash)                       | ✅                                   |
| [eth\_getUncleCountByBlockNumber ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetunclecountbyblocknumber)                   | ✅                                   |
| [eth\_getCode ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetcode)                                                         | ✅                                   |
| [eth\_sendRawTransaction ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fsendrawtransaction)                                   | ✅                                   |
| [eth\_call ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fcall)                                                               | ✅                                   |
| [eth\_estimateGas ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Festimategas)                                                 | ✅                                   |
| [eth\_getBlockByHash ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetblockbyhash)                                           | ✅                                   |
| [eth\_getBlockByNumber ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetblockbynumber)                                       | ✅                                   |
| [eth\_getTransactionByHash ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgettransactionbyhash)                               | ✅                                   |
| [eth\_getTransactionByBlockHashAndIndex ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgettransactionbyblockhashandindex)     | ✅                                   |
| [eth\_getTransactionByBlockNumberAndIndex ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgettransactionbyblocknumberandindex) | ✅                                   |
| [eth\_getTransactionReceipt ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgettransactionreceipt)                             | ✅                                   |
| [eth\_getUncleByBlockHashAndIndex ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetunclebyblockhashandindex)                 | ✅                                   |
| [eth\_getUncleByBlockNumberAndIndex ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetunclebyblocknumberandindex)             | ✅                                   |
| [eth\_getLogs ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetlogs)[2](#user-content-fn-1)                                  | ✅                                   |
| [eth\_getWork ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetwork)                                                         | ✅                                   |
| [eth\_getProof ↗](https://ethereum.github.io/execution-apis/api-documentation/)                                                                | ✅                                   |
| [net\_peerCount ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#net%5Fpeercount)                                                     | ❌                                   |
| [eth\_protocolVersion ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fprotocolversion)                                         | ❌                                   |
| [eth\_coinbase ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fcoinbase)                                                       | ❌                                   |
| [eth\_hashrate ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fhashrate)                                                       | ❌                                   |
| [eth\_accounts ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Faccounts)                                                       | ❌                                   |
| [eth\_sign ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fsign)                                                               | ❌                                   |
| [eth\_sendTransaction ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fsendtransaction)                                         | ❌                                   |
| [eth\_getCompilers ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetcompilers)                                               | ❌                                   |
| [eth\_compileLLL ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fcompilelll)                                                   | ❌                                   |
| [eth\_compileSolidity ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fcompile%5Fsolidity)                                      | ❌                                   |
| [eth\_compileSerpent ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fcompileserpent)                                           | ❌                                   |
| [eth\_newFilter ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fnewfilter)                                                     | ❌                                   |
| [eth\_newBlockFilter ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fnewblockfilter)                                           | ❌                                   |
| [eth\_newPendingTransactionFilter ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fnewpendingtransactionfilter)                 | ❌                                   |
| [eth\_uninstallFilter ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Funinstallfilter)                                         | ❌                                   |
| [eth\_getFilterChanges ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetfilterchanges)                                       | ❌                                   |
| [eth\_getFilterLogs ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fgetfilterlogs)                                             | ❌                                   |
| [eth\_submitWork ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fsubmitwork)                                                   | ❌                                   |
| [eth\_submitHashrate ↗](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth%5Fsubmithashrate)                                           | ❌                                   |

## Trace methods

EVM traces are a way to track the execution of smart contracts on the Ethereum blockchain. It records all the steps taken by the Ethereum Virtual Machine (EVM) as it runs the smart contract. This includes information like the specific operation that was executed, how much gas it cost, and any changes made to the blockchain as a result. The trace module is a tool that allows developers to access and analyze these traces, which can be useful for debugging, testing, and monitoring smart contracts. It can be used to identify and fix errors, optimize performance, and gain insight into how the smart contract is interacting with the blockchain.

### trace\_filter

The `trace_filter` method retrieves the traces of multiple transactions in a single request. This method is particularly useful for debugging and monitoring specific addresses on the Ethereum blockchain.

#### Request Parameters

* `fromBlock`: `Quantity` or `Tag` \- (optional) The block number to start receiving traces from.
* `toBlock`: `Quantity` or `Tag` \- (optional) The block number to stop receiving traces at.
* `fromAddress`: `Array` \- (optional) An array of addresses to start receiving traces from.
* `toAddress`: `Address` \- (optional) An array of addresses to stop retrieving traces at.
* `after`: `Quantity` \- (optional) The offset trace number
* `count`: `Quantity` \- (optional) The amount of traces to return.

#### Returns

This method returns an `Array` of traces matching the given filter.

#### Example

trace\_filter Request

```

curl https://web3-trial.cloudflare-eth.com/v1/mainnet \

-X POST \

-H 'Content-Type: application/json' \

--data '{

    "jsonrpc":"2.0",

    "method":"trace_filter",

    "params":[

        {

            "count": 200,

            "fromBlock": "0xccb943",

            "toBlock": "0xccbc62",

            "fromAddress": [

                "0xEdC763b3e418cD14767b3Be02b667619a6374076"

            ]

        }

    ],

    "id":1

    }'


```

#### Response

```

{

  "jsonrpc": "2.0",

  "result": [

    {

      "action": {

        "from": "0xedc763b3e418cd14767b3be02b667619a6374076",

        "callType": "call",

        "gas": "0x8462",

        "input": "0x095ea7b30000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",

        "to": "0x7ff4169a6b5122b664c51c95727d87750ec07c84",

        "value": "0x0"

      },

      "blockHash": "0x351e7c06ec010c8f7e7358eb580238dd23e1e129be96822aa93ebb6da08558e6",

      "blockNumber": 13416771,

      "result": {

        "gasUsed": "0x6009",

        "output": "0x0000000000000000000000000000000000000000000000000000000000000001"

      },

      "subtraces": 0,

      "traceAddress": [],

      "transactionHash": "0x054bbb9fbb855bf23f755e548c7409f45fc5eff8a824b2ad06380bc038d7b049",

      "transactionPosition": 54,

      "type": "call"

    }

  ],

  "id": 1

}


```

### Limitations

The `trace_filter` method has some limitations to ensure that our nodes are not overloaded.

* The block range for the `trace_filter` method is limited to 800 blocks.
* The trace `count` is limited to 200

## Footnotes

1. **Limitations**: Max block count of 10\. [↩](#user-content-fnref-2)
2. **Limitations**: Max block range of 800 blocks. [↩](#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":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/ethereum-gateway/","name":"Ethereum Gateway"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/ethereum-gateway/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/web3/ethereum-gateway/reference/supported-api-methods/","name":"Supported API methods"}}]}
```

---

---
title: Supported networks
description: Ethereum networks supported by the Cloudflare Ethereum Gateway.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Supported networks

Currently, Cloudflare Ethereum gateways support [interacting with](https://developers.cloudflare.com/web3/how-to/use-ethereum-gateway/) the following networks.

| Network                                                   | Usage                                                                                              |
| --------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| [Ethereum Mainnet ↗](https://ethereum.org/en/enterprise/) | Append /v1/mainnet to calls to your gateway or the Cloudflare public gateway (cloudflare-eth.com). |
| [Sepolia Testnet ↗](https://sepolia.dev/)                 | Append /v1/sepolia to calls to your gateway.                                                       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/ethereum-gateway/","name":"Ethereum Gateway"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/ethereum-gateway/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/web3/ethereum-gateway/reference/supported-networks/","name":"Supported networks"}}]}
```

---

## List Web3 Hostnames

**get** `/zones/{zone_id}/web3/hostnames`

List Web3 Hostnames

### Path Parameters

- `zone_id: string`

  Specify the identifier of the hostname.

### Returns

- `errors: array of ResponseInfo`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of ResponseInfo`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

- `result: array of Hostname`

  - `id: optional string`

    Specify the identifier of the hostname.

  - `created_on: optional string`

  - `description: optional string`

    Specify an optional description of the hostname.

  - `dnslink: optional string`

    Specify the DNSLink value used if the target is ipfs.

  - `modified_on: optional string`

  - `name: optional string`

    Specify the hostname that points to the target gateway via CNAME.

  - `status: optional "active" or "pending" or "deleting" or "error"`

    Specifies the status of the hostname's activation.

    - `"active"`

    - `"pending"`

    - `"deleting"`

    - `"error"`

  - `target: optional "ethereum" or "ipfs" or "ipfs_universal_path"`

    Specify the target gateway of the hostname.

    - `"ethereum"`

    - `"ipfs"`

    - `"ipfs_universal_path"`

- `success: true`

  Specifies whether the API call was successful.

  - `true`

- `result_info: optional object { count, page, per_page, total_count }`

  - `count: optional number`

    Specifies the total number of results for the requested service.

  - `page: optional number`

    Specifies the current page within paginated list of results.

  - `per_page: optional number`

    Specifies the number of results per page of results.

  - `total_count: optional number`

    Specifies the total results available without any search parameters.

### Example

```http
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/web3/hostnames \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "result": [
    {
      "id": "023e105f4ecef8ad9ca31a8372d0c353",
      "created_on": "2014-01-01T05:20:00.12345Z",
      "description": "This is my IPFS gateway.",
      "dnslink": "/ipns/onboarding.ipfs.cloudflare.com",
      "modified_on": "2014-01-01T05:20:00.12345Z",
      "name": "gateway.example.com",
      "status": "active",
      "target": "ipfs"
    }
  ],
  "success": true,
  "result_info": {
    "count": 1,
    "page": 1,
    "per_page": 20,
    "total_count": 2000
  }
}
```

---

---
title: Customize Cloudflare settings
description: Apply Cloudflare security and performance settings to your Web3 gateway.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Customize Cloudflare settings

Once your gateway becomes [active](https://developers.cloudflare.com/web3/reference/gateway-status/), you can customize the Cloudflare settings associated with your hostname.

Since your traffic is automatically proxied through Cloudflare, you customize your website settings to take advantage of various [security, performance, and reliability](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/#cloudflare-as-a-reverse-proxy) benefits.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/how-to/customize-cloudflare-settings/","name":"Customize Cloudflare settings"}}]}
```

---

---
title: Subscribe to gateways
description: Subscribe to Ethereum or IPFS gateways on your Cloudflare account.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Subscribe to gateways

Before you can [create a new gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/#create-a-gateway), you need to subscribe to one or more gateways.

## Create new subscription

To subscribe to a Web3 gateway (if you have not already subscribed):

1. In the Cloudflare dashboard, go to the **Web3** page.  
[ Go to **Web3** ](https://dash.cloudflare.com/?to=/:account/:zone/web3)
2. Click **Subscribe to Web3 Gateways**.
3. Choose which gateways you want to subscribe to.
4. Click **Proceed to Payment Details**.
5. Enter your payment information (if not already attached to your account) and complete your purchase.

Note

Enterprise customers can preview this product as a [non-contract service](https://developers.cloudflare.com/billing/understand/preview-services/), which provides full access, free of metered usage fees, limits, and certain other restrictions.

## Manage existing subscription

To update an existing subscription or subscribe to an additional gateway:

1. In the Cloudflare dashboard, go to the **Web3** page.  
[ Go to **Web3** ](https://dash.cloudflare.com/?to=/:account/:zone/web3)
2. Click **Manage Subscriptions**.
3. To update existing gateway subscriptions, click **Change**. To purchase access to a new gateway, click **Subscribe**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/how-to/enable-gateways/","name":"Subscribe to gateways"}}]}
```

---

---
title: Manage gateways
description: Create, edit, and delete Web3 gateways.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Manage gateways

A Cloudflare Web3 gateway provides HTTP-accessible interfaces to various Web3 networks. You can interact with a gateway in several ways.

## Create a gateway

* [ Dashboard ](#tab-panel-11138)
* [ API ](#tab-panel-11139)

To create a gateway using the dashboard:

1. In the Cloudflare dashboard, go to the **Web3** page.  
[ Go to **Web3** ](https://dash.cloudflare.com/?to=/:account/:zone/web3)
2. Click **Create Gateway**.
3. Enter the following information:
* **Hostname**: Enter a hostname to use as your gateway, which has to be a subdomain of the current Cloudflare zone.
* **Gateway Description**: Enter a description to help distinguish between different gateways.
* **Gateway Type**: Select a gateway target of [IPFS DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/), [IPFS Universal Path](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/universal-gateway/), or [Ethereum](https://developers.cloudflare.com/web3/ethereum-gateway/).
* **DNSLink**: Only applicable to IPFS gateways, more details at [DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/#how-is-it-used-with-cloudflare).
1. Click **Deploy**.

To create a gateway using the API, send a [POST](https://developers.cloudflare.com/api/resources/web3/subresources/hostnames/methods/create/) request that includes the following parameters:

* `name`: The hostname that will point to the target gateway via a `CNAME` record.
* `target`: The gateway target for the hostname (`ethereum`, `ipfs`, `ipfs_universal_path`).

If you need help with API authentication, refer to [Cloudflare API documentation](https://developers.cloudflare.com/fundamentals/api/).

Request

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/web3/hostnames" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data '{

  "name": "gateway.example.com",

  "description": "This is my IPFS gateway.",

  "target": "ipfs",

  "dnslink": "/ipns/onboarding.ipfs.cloudflare.com"

}'


```

The response contains the complete definition of the new gateway.

Response

```

{

  "success": true,

  "errors": [],

  "messages": [],

  "result": {

    "id": "<WEB3_GATEWAY_ID>",

    "name": "gateway.example.com",

    "description": "This is my IPFS gateway.",

    "status": "active",

    "target": "ipfs",

    "dnslink": "/ipns/onboarding.ipfs.cloudflare.com",

    "created_on": "<CREATED_ON_DATE>",

    "modified_on": "<MODIFIED_ON_DATE>"

  }

}


```

When you create a gateway, Cloudflare automatically:

* Creates and adds [records to your Cloudflare DNS](https://developers.cloudflare.com/web3/reference/gateway-dns-records/) so your gateway can receive and route traffic appropriately.
* [Proxies](https://developers.cloudflare.com/dns/proxy-status/) traffic to that hostname.
* Issues an SSL/TLS certificate to cover the specified hostname.

---

## Edit a gateway

Once you have [created a gateway](#create-a-gateway), you can only edit the **Gateway Description** and — if it is an **IPFS** gateway — also edit the value for the [DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/) field.

If you need to edit other fields, [delete the gateway](#delete-a-gateway) and create a new one.

* [ Dashboard ](#tab-panel-11130)
* [ API ](#tab-panel-11131)

To edit a gateway using the dashboard:

1. In the Cloudflare dashboard, go to the **Web3** page.  
[ Go to **Web3** ](https://dash.cloudflare.com/?to=/:account/:zone/web3)
2. On a specific gateway, click **Edit**.
3. Update the **Gateway Description** and — if editing an **IPFS** gateway — the value for the [DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/).
4. Click **Reapply**.

To edit specific settings for a gateway, use a [PATCH](https://developers.cloudflare.com/api/resources/web3/subresources/hostnames/methods/edit/) request.

---

## Refresh a gateway

When your gateway is stuck in an **Error** [status](https://developers.cloudflare.com/web3/reference/gateway-status/), you should try refreshing the gateway, which attempts to re-create the associated DNS records for the hostname.

* [ Dashboard ](#tab-panel-11132)
* [ API ](#tab-panel-11133)

To refresh a gateway using the dashboard:

1. In the Cloudflare dashboard, go to the **Web3** page.  
[ Go to **Web3** ](https://dash.cloudflare.com/?to=/:account/:zone/web3)
2. On a gateway, click the dropdown then **Refresh**.

To refresh a gateway using the API, send a [PATCH](https://developers.cloudflare.com/api/resources/web3/subresources/hostnames/methods/edit/) request with an empty request body.

---

## Update blocklist

When you set up a [IPFS Universal Path gateway](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/universal-gateway/), you may want to add items to the gateway blocklist, which allows you to block access to specific content.

You have the ability to block access to one or more:

* CIDs (`QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB`)
* IPFS content paths (`/ipfs/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG/readme`)
* IPNS content paths (`/ipns/example.com`)

* [ Dashboard ](#tab-panel-11134)
* [ API ](#tab-panel-11135)

To add an item to the blocklist using the dashboard:

1. In the Cloudflare dashboard, go to the **Web3** page.  
[ Go to **Web3** ](https://dash.cloudflare.com/?to=/:account/:zone/web3)
2. On a specific gateway, click the dropdown then **Blocklist**.
3. Click **Add entry**.
4. Enter the following information:  
   * **Blocklist entry type**: Choose **CID** or **Content path**.  
   * **Blocklist entry content**: Add a CID or content path to block, meaning either a valid CIDv0 or CIDv1 string (CID) or the entry should start with `/ipfs/` or `/ipns/` (content path).  
   * **Blocklist entry description**: Add a description to help you identify the blocklist entry.
5. Click **Add**.

To add a blocklist item using the API, send a [POST](https://developers.cloudflare.com/api/resources/web3/subresources/hostnames/subresources/ipfs%5Funiversal%5Fpaths/subresources/content%5Flists/subresources/entries/methods/create/) request.

---

## Delete a gateway

When you delete a gateway, Cloudflare will automatically remove all associated hostname DNS records. This action will impact your traffic and cannot be undone.

* [ Dashboard ](#tab-panel-11136)
* [ API ](#tab-panel-11137)

To delete a gateway using the dashboard:

1. In the Cloudflare dashboard, go to the **Web3** page.  
[ Go to **Web3** ](https://dash.cloudflare.com/?to=/:account/:zone/web3)
2. On a specific gateway, click the dropdown then **Remove**.
3. Click **Delete hostname**.

To delete a gateway using the API, send a [DELETE](https://developers.cloudflare.com/api/resources/web3/subresources/hostnames/methods/delete/) request.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/how-to/manage-gateways/","name":"Manage gateways"}}]}
```

---

---
title: Restrict gateway access
description: Restrict access to your Web3 gateway with WAF custom rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Restrict gateway access

If you are using a [Web3 gateway](https://developers.cloudflare.com/web3/about/) for internal application calls, you may want to restrict gateway access to specific backend services.

You can achieve this goal by [creating general Access policies](https://developers.cloudflare.com/cloudflare-one/access-controls/policies/) to block normal traffic and then [creating service tokens](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/service-tokens/) to allow access by your backend service.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/how-to/restrict-gateway-access/","name":"Restrict gateway access"}}]}
```

---

---
title: Use Ethereum gateway
description: Send JSON-RPC requests through the Cloudflare Ethereum Gateway.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Use Ethereum gateway

Once you have an Ethereum gateway — meaning that you [create a new gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/#create-a-gateway) with a `target` of **Ethereum** — you can interact with [different Ethereum networks](https://developers.cloudflare.com/web3/ethereum-gateway/reference/supported-networks/) by specifying the correct JSON blob for your query.

## Read from the network

The Cloudflare Ethereum Gateway allows HTTP requests where the body of the request is set to be the JSON body of the request you would like to make. For example, if you would like to read the block that is at number `0x2244`, then your JSON blob takes the form:

```

{

  "jsonrpc": "2.0",

  "method": "eth_getBlockByNumber",

  "params": ["0x2244", true],

  "id": 1

}


```

Each blob use a valid [method parameter](https://developers.cloudflare.com/web3/ethereum-gateway/reference/supported-api-methods/). The `params` array here contains the block number that we would like to locate and a boolean expressing whether each individual transaction in the block should be shown in their entirety (`true`) or as stubs (`false`).

To send this query to your [custom Ethereum Gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/), you could use a cURL command:

Terminal window

```

curl https://web3-trial.cloudflare-eth.com/v1/mainnet -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x2244", true],"id":1}'


```

You can also write the same query using the JS Fetch API:

JavaScript

```

await fetch(

  new Request("https://web3-trial.cloudflare-eth.com/v1/mainnet", {

    method: "POST",

    body: JSON.stringify({

      jsonrpc: "2.0",

      method: "eth_getBlockByNumber",

      params: ["0x2244", true],

      id: 1,

    }),

    headers: {

      "Content-Type": "application/json",

    },

  }),

).then((resp) => {

  return resp.json();

});


```

The response in both cases will be a JSON blob of the form:

```

{

  "jsonrpc": "2.0",

  "id": 1,

  "result": {

    "difficulty": "0x746ef15b66",

    "extraData": "0x476574682f76312e302e302f6c696e75782f676f312e342e32",

    "gasLimit": "0x1388",

    "gasUsed": "0x0",

    "hash": "0xd6bb42034740c5d728e774e43a01f26222e0fcc279c504ca5963dc34fe70f392",

    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",

    "miner": "0xf927a40c8b7f6e07c5af7fa2155b4864a4112b13",

    "mixHash": "0x975da446e302e6da6cedb3fbaa763c3c203ae88d6fab4924e2a3d34a568c4361",

    "nonce": "0x88a7f12f49151c83",

    "number": "0x2244",

    "parentHash": "0x067fd84ecdbc7491bf5ec7d5d4ead361b1f590eec74797a7f90b4a7d7004a48d",

    "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",

    "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",

    "size": "0x21b",

    "stateRoot": "0x828dade2067283e370993ec6a1bda0e65c1310e404a6d5bbb030b596eb80017c",

    "timestamp": "0x55bb040f",

    "totalDifficulty": "0x5c328da43525d",

    "transactions": [],

    "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",

    "uncles": []

  }

}


```

## Write to the network

Currently, the Ethereum Gateway allows you to write to the network using the `eth_sendRawTransaction` RPC method. This creates a new message call transaction or a contract creation for signed transactions. The transactions are signed using a secret key corresponding to your own [Ethereum wallet ↗](https://www.ethereum.org/use/#%5F3-what-is-a-wallet-and-which-one-should-i-use).

Once you have a wallet set up and a method of signing your own transactions, you can write that transaction to the Ethereum network via the [Cloudflare Ethereum Gateway](https://developers.cloudflare.com/web3/ethereum-gateway/reference/supported-api-methods/). Signed transactions use hexadecimal strings of the form:

```

"0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"


```

Then you can use your [custom Gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/) to send the transaction to the network with a cURL command:

Terminal window

```

curl https://web3-trial.cloudflare-eth.com/v1/mainnet -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":["0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"],"id":1}'


```

You could also use a JS Fetch API request:

JavaScript

```

await fetch(

  new Request("https://web3-trial.cloudflare-eth.com/v1/mainnet", {

    method: "POST",

    body: JSON.stringify({

      jsonrpc: "2.0",

      method: "eth_sendRawTransaction",

      params: [

        "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675",

      ],

      id: 1,

    }),

    headers: {

      "Content-Type": "application/json",

    },

  }),

).then((resp) => {

  return resp.json();

});


```

_(The actual command above will not work — you need to provide your own signed transaction.)_

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/how-to/use-ethereum-gateway/","name":"Use Ethereum gateway"}}]}
```

---

---
title: Use IPFS gateway
description: Serve IPFS content through the Cloudflare IPFS Gateway.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Use IPFS gateway

Once you have an IPFS gateway — meaning that you [create a new gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/#create-a-gateway) with a `target` of **IPFS** — you can get data from the IPFS network by using a URL.

## Read from the network

Every time you access a piece of content through Cloudflare's IPFS Gateway, you need a URL with two parts: the gateway hostname and the request path.

### Gateway hostname

Your gateway hostname will be the **Hostname** value you supplied when you [created the gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/#create-a-gateway).

### Request path

The request path will vary based on the type of content you are serving.

If a request path is `/ipfs/<CID_HASH>`, that tells the gateway that you want the content with the Content Identifier (CID) that immediately follows. Because the content is addressed by CID, the gateway's response is immutable and will never change. An example would be `https://cloudflare-ipfs.com/ipfs/QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco/wiki/`, which is a mirror of Wikipedia and an immutable `/ipfs/` link.

If a request path is `/ipns/<DOMAIN>`, that tells the gateway that you want it to lookup the CID associated with a given domain in DNS and then serve whatever content corresponds to the CID it happens to find. Because DNS can change over time, so will the gateway's response. An example would be `https://cloudflare-ipfs.com/ipns/ipfs.tech/`, which is IPFS's marketing site and can be changed at any time by modifying the [DNSLink record](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/) associated with the `ipfs.tech` domain.

## Write to the network

Cloudflare's IPFS Gateway is currently limited to read-only access.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/how-to/","name":"How to"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/how-to/use-ipfs-gateway/","name":"Use IPFS gateway"}}]}
```

---

---
title: Gateway DNS records
description: DNS records created for Web3 gateways.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Gateway DNS records

Once you [create a gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/#create-a-gateway), Cloudflare automatically creates and adds records to your Cloudflare DNS so your gateway can receive and route traffic appropriately:

* **Ethereum gateways**: Creates a [proxied](https://developers.cloudflare.com/dns/proxy-status/) `CNAME` record pointing your hostname to `ethereum.cloudflare.com`.
* **IPFS gateways**: Creates a [proxied](https://developers.cloudflare.com/dns/proxy-status/) `CNAME` record pointing your hostname to `ipfs.cloudflare.com` and a `TXT` record with the value specified for its [DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/#how-is-it-used-with-cloudflare).

These records cannot be edited within Cloudflare DNS. To make edits, you will have to [edit the gateway configuration](https://developers.cloudflare.com/web3/how-to/manage-gateways/#edit-a-gateway) itself.

## Existing DNS records

When you [create a gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/#create-a-gateway) using a hostname with pre-existing DNS records, Cloudflare automatically overwrites your existing records to make them apply to your Web3 gateway.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/reference/gateway-dns-records/","name":"Gateway DNS records"}}]}
```

---

---
title: Gateway status
description: Web3 gateway status values and their meanings.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Gateway status

Once you [create a gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/#create-a-gateway), it can have one of several statuses.

| Status       | Definition                                                                                                                                                                                  |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Active**   | The DNS records for your gateway have been created and are functioning correctly.                                                                                                           |
| **Pending**  | Your Web3 gateway is in the process of becoming **Active**.                                                                                                                                 |
| **Deleting** | Your Web3 gateway is being deleted.                                                                                                                                                         |
| **Error**    | The DNS records for your gateway are misconfigured or do not exist. To fix, try [refreshing the gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/#refresh-a-gateway). |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/reference/gateway-status/","name":"Gateway status"}}]}
```

---

---
title: Limits
description: Rate limits and size limits for Web3 gateways.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Limits

The following limits apply to users of the Cloudflare Web3 Gateways.

Note

For more pricing details, refer to the [Web3 product page ↗](https://www.cloudflare.com/application-services/products/web3/).

## IPFS Gateway

The following limits apply to Cloudflare's [IPFS Gateway](https://developers.cloudflare.com/web3/ipfs-gateway/).

| Free                                         | Pro                                                                              | Business                                                                         | Enterprise                                                                       |                                                                                                                                                                                       |
| -------------------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Availability                                 | Yes (Usage-based billing)                                                        | Yes (Usage-based billing)                                                        | Yes (Usage-based billing)                                                        | Yes (Usage-based billing)                                                                                                                                                             |
| Total gateways                               | 15                                                                               | 15                                                                               | 15                                                                               | Unlimited                                                                                                                                                                             |
| Gateway types                                | [DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/) | [DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/) | [DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/) | [DNSLink](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/dnslink/),[Universal Gateway](https://developers.cloudflare.com/web3/ipfs-gateway/concepts/universal-gateway/) |
| Included bandwidth (without additional cost) | 50 GB data transfer                                                              | 50 GB data transfer                                                              | 50 GB data transfer                                                              | 100 GB data transfer                                                                                                                                                                  |
| File size limit                              | None                                                                             | None                                                                             | None                                                                             | None                                                                                                                                                                                  |

## Ethereum Gateway

The following limits apply to Cloudflare's [Ethereum Gateway](https://developers.cloudflare.com/web3/ethereum-gateway/).

| Free                                          | Pro                       | Business                  | Enterprise                |                           |
| --------------------------------------------- | ------------------------- | ------------------------- | ------------------------- | ------------------------- |
| Availability                                  | Yes (Usage-based billing) | Yes (Usage-based billing) | Yes (Usage-based billing) | Yes (Usage-based billing) |
| Total gateways                                | 15                        | 15                        | 15                        | Unlimited                 |
| Included bandwidth  (without additional cost) | 500,000 HTTP requests     | 500,000 HTTP requests     | 500,000 HTTP requests     | 1,000,000 HTTP requests   |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/reference/limits/","name":"Limits"}}]}
```

---

---
title: Legacy gateway migration
description: Migrate from legacy Web3 gateways to the current setup.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Legacy gateway migration

As announced in [our blog post ↗](https://blog.cloudflare.com/ea-web3-gateways/), Cloudflare is deprecating legacy hostnames that point to our public gateway endpoints at `cloudflare-eth.com` and `cloudflare-ipfs.com`.

If you created a hostname pointing to these gateways during the [private beta ↗](https://blog.cloudflare.com/announcing-web3-gateways/), you should migrate to use our new Web3 gateways to avoid a disruption in service.

---

## Migration guide

The migration is a simple process.

First, create a [Cloudflare account](https://developers.cloudflare.com/fundamentals/account/create-account/).

Then create a new [Web3 custom gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/#create-a-gateway) with your existing hostname.

Alternatively, you could also create a [Web3 custom gateway](https://developers.cloudflare.com/web3/how-to/manage-gateways/#create-a-gateway) for a new hostname and then modify your application to use your newly created hostname ([IPFS](https://developers.cloudflare.com/web3/how-to/use-ipfs-gateway/) or [Ethereum](https://developers.cloudflare.com/web3/how-to/use-ethereum-gateway/)).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/web3/","name":"Web3"}},{"@type":"ListItem","position":3,"item":{"@id":"/web3/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/web3/reference/migration-guide/","name":"Legacy gateway migration"}}]}
```

---

---
title: Cloudflare API Shield
description: Identify and address API vulnerabilities with discovery, schema validation, and abuse detection.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare API Shield

Identify and address your API vulnerabilities.

 Enterprise-only paid add-on 

Note

Enterprise customers can preview this product as a [non-contract service](https://developers.cloudflare.com/billing/understand/preview-services/), which provides full access, free of metered usage fees, limits, and certain other restrictions.

## Why care about API security?

APIs have become the [backbone of popular web services ↗](https://blog.postman.com/intro-to-apis-history-of-apis/), helping the Internet become more accessible and useful.

As APIs have become more prevalent, however, so have their problems:

* Many companies have [thousands of APIs](https://developers.cloudflare.com/api-shield/security/api-discovery/), including ones they do not even know about.
* To support a large base of users, many APIs are protected by a negative security model that makes them vulnerable to credential-stuffing attacks and automated scanning tools.
* With so many endpoints and users, it’s difficult to recognize brute-force attacks against [specific endpoints](https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/).
* Sophisticated attacks are even harder to recognize, often because even development teams are unaware of common and uncommon [usage patterns](https://developers.cloudflare.com/api-shield/security/sequence-analytics/).

Refer to the [Get started](https://developers.cloudflare.com/api-shield/get-started/) guide to set up API Shield.

## Features

###  Security features 

Secure your APIs using API Shield's security features.

[ Use Security features ](https://developers.cloudflare.com/api-shield/security/) 

###  Management, monitoring, and more 

Monitor the health of your API endpoints.

[ Use Management, monitoring, and more ](https://developers.cloudflare.com/api-shield/management-and-monitoring/) 

## Availability

Cloudflare API Security products are available to Enterprise customers only, though anyone can set up [Mutual TLS](https://developers.cloudflare.com/api-shield/security/mtls/) with a Cloudflare-managed certificate authority.

The full API Shield security suite is available as an Enterprise-only paid add-on, but all customers can access [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/) and [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/) functionalities.

Note

API Shield currently does not work for JDCloud customers.

## Related products

**[DDoS Protection](https://developers.cloudflare.com/ddos-protection/)** 

Cloudflare DDoS protection secures websites, applications, and entire networks while ensuring the performance of legitimate traffic is not compromised.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}}]}
```

---

---
title: Get started with API Shield
description: Set up API Shield to identify and address API security best practices.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started with API Shield

API Shield protects your APIs by discovering endpoints, validating request schemas, and detecting abuse patterns. This guide walks through the initial setup from configuring session identifiers to enabling advanced protections.

Note

Enabling API Shield features will have no impact on your traffic until you choose to move a setting from `log` to `block` mode.

## Session identifiers

While not strictly required, it is recommended that you configure your session identifiers when getting started with API Shield. When Cloudflare inspects your API traffic for individual sessions, we can offer more tools for visibility, management, and control.

If you are unsure of the session identifiers that your API uses, consult with your development team.

Session identifiers should uniquely identify API clients. A common session identifier for API traffic is the `Authorization` header. When a [JSON Web Token (JWT)](https://developers.cloudflare.com/api-shield/security/jwt-validation/) is used by the API for client authentication, its value may change over time. You can use a claim value inside the JWT such as `sub` or `email` as a session ID to uniquely identify the session over time.

If your API uses the `Authorization` header on more than 1% of successful requests to your zone, Cloudflare will automatically set it as the API Shield session identifier.

You must have specific entitlements to configure session identifiers or cookies as a form of identifiers, such as an Enterprise subscription, for features such as [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/), [Sequence Mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/) or [rate limiting recommendations](https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/), and to see results in [Sequence Analytics](https://developers.cloudflare.com/api-shield/security/sequence-analytics/) and [Authentication Posture](https://developers.cloudflare.com/api-shield/security/authentication-posture/).

### To set up session identifiers

* [  New dashboard ](#tab-panel-6529)
* [ Old dashboard ](#tab-panel-6530)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **API abuse**.
3. On **Session identifiers**, select **Configure session identifiers**.
4. Select **Manage identifiers**.
5. Choose the type of session identifier (cookie, HTTP header, or JWT claim).  
Note  
The session identifier cookie must comply with RFC 6265\. Otherwise, it will be rejected.  
If you are using a JWT claim, choose the [Token Configuration](https://developers.cloudflare.com/api-shield/security/jwt-validation/api/#token-configurations) that will verify the JWT. Token Configurations are required to use JWT claims as session identifiers. Refer to [JWT Validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/) for more information.
6. Enter the name of the session identifier.
7. Select **Save**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/login), and select your account and domain.
2. Go to **Security** \> **API Shield**.
3. Select **Settings**.
4. On **Endpoint settings**, select **Manage identifiers**.
5. Choose the type of session identifier (cookie, HTTP header, or JWT claim).  
Note  
The session identifier cookie must comply with RFC 6265\. Otherwise, it will be rejected.  
If you are using a JWT claim, choose the [Token Configuration](https://developers.cloudflare.com/api-shield/security/jwt-validation/api/#token-configurations) that will verify the JWT. Token Configurations are required to use JWT claims as session identifiers. Refer to [JWT Validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/) for more information.
6. Enter the name of the session identifier.
7. Select **Save**.

After setting up session identifiers and allowing some time for Cloudflare to learn your traffic patterns, you can view your per endpoint and per session rate limiting recommendations, as well as enforce per endpoint and per session rate limits by creating new rules. Session identifiers will allow you to view API Discovery results from session ID-based discovery and session traffic patterns in Sequence Analytics.

## Upload a schema using Schema validation (optional)

Schema validation protects your APIs by checking incoming requests against your API schema. Depending on your configured action, requests that do not match the schema are logged or blocked.

When you upload a schema via the Cloudflare dashboard, its endpoints are automatically added to Endpoint Management. If you already have an OpenAPI specification, upload it to [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/).

Note

It is recommended to start with Schema validation rules set to `log` to review logged requests in [Security Events](https://developers.cloudflare.com/waf/analytics/security-events/). When you are confident that only the correct requests are logged, you should switch the rule to `block`.

If you do not have a schema to upload, continue reading this guide to learn how to generate a schema with API Shield.

## Enable the Sensitive Data Detection ruleset and accompanying rules

API Shield works with the Cloudflare [WAF](https://developers.cloudflare.com/waf/) [Sensitive Data Detection](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/#sensitive-data-detection) ruleset to identify API endpoints that return sensitive data, such as social security or credit card numbers, in their HTTP responses. Review these endpoints to verify that sensitive data is only returned where expected.

Note

Sensitive Data Detection requires a separate subscription. Contact your account team if your plan does not include this feature.

You can identify endpoints returning sensitive data by selecting the icon next to the path in a row. Expand the endpoint to see details on which rules were triggered and view more information by exploring events in **Firewall Events**.

## Add your discovered endpoints to Endpoint Management

Cloudflare automatically discovers API endpoints by inspecting your traffic. Adding these discovered endpoints to [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/) unlocks additional security and monitoring features.

Endpoint Management tracks request counts, error rates, and latency for each saved endpoint.

Note

Schema validation, schema learning, JWT validation, Sequence Analytics, sequence mitigation, and rate limit recommendations only run on endpoints saved to Endpoint Management.

You can save your endpoints directly from [API Discovery](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/#add-endpoints-from-api-discovery), [Schema validation](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/#add-endpoints-from-schema-validation), or [manually](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/#add-endpoints-manually) by method, path, and host.

You can view your list of saved endpoints in the **Endpoint Management** page. Cloudflare will aggregate [performance data](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/#endpoint-analysis) and security data on your endpoint once it is saved.

### Allow the system to learn your traffic patterns

After you add an endpoint, Cloudflare begins learning schema parameters from your API traffic. Endpoints must be saved for at least 24 hours before schema learning begins. Schema learning is a continuous process that inspects the most recent 72 hours of traffic. Endpoints with higher traffic volumes produce more accurate schemas.

Cloudflare also uses your configured session identifiers to generate rate limit recommendations for each endpoint.

Allow at least 24 hours after adding endpoints before proceeding to the schema and rate limit steps below.

While the system learns your traffic patterns, you can continue with [additional configurations](https://developers.cloudflare.com/api-shield/get-started/#additional-configuration) such as JWT validation or mTLS.

## Add rate limits to your most sensitive endpoints

[Rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/) allow you to define rate limits for requests matching an expression, and choose the action to perform when those rate limits are reached.

API Shield generates rate limit recommendations for each endpoint based on your session identifiers. These recommendations are scoped per endpoint and per session rather than applied across your entire site or based on IP address.

Per-session rate limits track traffic from individual visitors during their session to a specific endpoint. This reduces false positives from broadly scoped rules while still limiting abusive traffic.

## Import a learned schema to Schema validation

Cloudflare learns schema parameters by inspecting request traffic for all endpoints saved to Endpoint Management. You can export the learned schema as an OpenAPI v3.0.0 specification by hostname.

Import the learned schema into Schema validation to protect endpoints that Cloudflare discovered through traffic inspection — including endpoints you may not have had a schema for previously.

You can import the learned schema of an entire hostname using the [Cloudflare dashboard](https://developers.cloudflare.com/api-shield/security/schema-validation/#add-validation-by-applying-a-learned-schema-to-an-entire-hostname). Alternatively, you can [apply learned schemas to individual endpoints](https://developers.cloudflare.com/api-shield/security/schema-validation/#add-validation-by-applying-a-learned-schema-to-a-single-endpoint). Before applying a learned schema, export and review it to verify the schema accurately represents your expected traffic patterns.

## Export a learned schema from Endpoint Management

Learned schemas include the hostname, all endpoints by host, method, and path, and detected path variables (for example, `/users/{id}`). They can also include detected query parameters and their format. You can optionally include rate limit threshold recommendations.

You can export your learned schemas in the [Cloudflare dashboard](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/#export-a-schema) or via the [API](https://developers.cloudflare.com/api/resources/api%5Fgateway/subresources/schemas/methods/list/).

## View and configure Sequence Analytics

[Sequence Analytics](https://developers.cloudflare.com/api-shield/security/sequence-analytics/) identifies common patterns of API requests — for example, a user checking their account balance before initiating a funds transfer.

Sequences are ranked by precedence score, which measures how likely specific API requests are to occur together in a consistent order. High-scoring sequences contain API requests that are likely to be preceded by the other operations in the sequence.

[Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/) allows you to enforce request patterns for authenticated clients communicating with your API. Use Sequence Analytics to identify the sequences your API clients follow, then apply API Shield protections (rate limiting, Schema validation, JWT validation, and mTLS) to the endpoints in your high-scoring sequences. Verify the expected endpoint order with your development team.

For more information, refer to [Detecting API abuse automatically using sequence analysis ↗](https://blog.cloudflare.com/api-sequence-analytics) blog post.

## Additional configuration

### Set up JSON Web Tokens (JWT) validation

[JSON Web Tokens (JWT) validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/) verifies that tokens sent by clients have not been tampered with and have not expired. Configure JWT validation using the Cloudflare dashboard or API.

### Set up GraphQL malicious query protection

If your origin uses GraphQL, you may consider setting limits on GraphQL query size and depth.

[GraphQL malicious query protection](https://developers.cloudflare.com/api-shield/security/graphql-protection/api/) scans GraphQL traffic for queries with excessive nesting or size that could overload your origin and result in a denial of service. You can create rules that set maximum query depth and size to block these queries before they reach your origin.

For more information, refer to the [blog post ↗](https://blog.cloudflare.com/protecting-graphql-apis-from-malicious-queries/).

### Mutual TLS (mTLS) authentication

If you operate an API that requires or would benefit from an extra layer of protection, you may consider using Mutual TLS (mTLS).

[Mutual TLS (mTLS) authentication](https://developers.cloudflare.com/api-shield/security/mtls/) requires both the client and server to verify each other's identity using certificates. In standard TLS, only the server proves its identity. mTLS adds client verification, which is useful for devices like IoT hardware that do not authenticate via an identity provider.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/get-started/","name":"Get started with API Shield"}}]}
```

---

---
title: Plans
description: Compare API Shield feature availability and endpoint limits across Cloudflare plans.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Plans

Free, Pro, Business, and Enterprise customers without an API Shield subscription can access [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/) and [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), but no other [API Shield](https://developers.cloudflare.com/api-shield/) features.

To subscribe to API Shield, upgrade to an Enterprise plan and contact your account team.

Limits to endpoints apply to Endpoint Management and Schema validation. Refer to the table below for limits based on your zone plan.

| Plan type                         | Saved endpoints | Uploaded schemas | Total uploaded schema size | Rule action  |
| --------------------------------- | --------------- | ---------------- | -------------------------- | ------------ |
| **Free**                          | 100             | 5                | 200 kB                     | Block only   |
| **Pro**                           | 250             | 5                | 500 kB                     | Block only   |
| **Business**                      | 500             | 10               | 2 MB                       | Block only   |
| **Enterprise without API Shield** | 500             | 10               | 5 MB                       | Log or Block |
| **Enterprise with API Shield**    | 10,000          | 10+              | 10+ MB                     | Log or Block |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/plans/","name":"Plans"}}]}
```

---

---
title: Security
description: Discover, validate, and protect API endpoints with API Shield security features.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Security

Cloudflare offers the following features to help secure your APIs:

| Discovery & management                                                                                                         | Posture management                                                                                                  | Runtime protection                                                                                |
| ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/)                                          | [Volumetric Abuse Detection](https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/)     | [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/)     |
| [Schema learning](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/) | [Authentication Posture](https://developers.cloudflare.com/api-shield/security/authentication-posture/)             | [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/)           |
| [Sequence Analytics](https://developers.cloudflare.com/api-shield/security/sequence-analytics/)                                | [BOLA vulnerability detection](https://developers.cloudflare.com/api-shield/security/bola-vulnerability-detection/) | [Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/) |
| [Risk labels](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/#risk-labels)             | [Mutual TLS (mTLS)](https://developers.cloudflare.com/api-shield/security/mtls/)                                    |                                                                                                   |
| [Vulnerability Scanner](https://developers.cloudflare.com/api-shield/security/vulnerability-scanner/)                          | [GraphQL query protection](https://developers.cloudflare.com/api-shield/security/graphql-protection/)               |                                                                                                   |

## Example Cloudflare solutions

Cloudflare API Shield, together with other Cloudflare products, helps protect your API from the [OWASP API Security Top 10 ↗](https://owasp.org/www-project-api-security/). These are the most common API security risks, ranging from unauthorized data access to denial of service.

The following table maps each OWASP vulnerability to the Cloudflare features that address it:

| OWASP issue                                     | Example Cloudflare solution                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Broken Object Level Authorization               | [BOLA vulnerability detection](https://developers.cloudflare.com/api-shield/security/bola-vulnerability-detection/), [Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/), [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/), [Rate Limiting](https://developers.cloudflare.com/waf/rate-limiting-rules/), [Vulnerability Scanner](https://developers.cloudflare.com/api-shield/security/vulnerability-scanner/) |
| Broken Authentication                           | [Authentication Posture](https://developers.cloudflare.com/api-shield/security/authentication-posture/), [mTLS](https://developers.cloudflare.com/api-shield/security/mtls/), [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/), [Exposed Credential Checks](https://developers.cloudflare.com/waf/managed-rules/check-for-exposed-credentials/), [Bot Management](https://developers.cloudflare.com/bots/)                                                                                                                                                  |
| Broken Object Property Level Authorization      | [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/)                                                                                                                                                                                                                                                                                                                                                                                                             |
| Unrestricted Resource Consumption               | [Rate Limiting](https://developers.cloudflare.com/waf/rate-limiting-rules/), [Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/), [Bot Management](https://developers.cloudflare.com/bots/), [GraphQL Query Protection](https://developers.cloudflare.com/api-shield/security/graphql-protection/)                                                                                                                                                                                                                                                   |
| Broken Function Level Authorization             | [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/)                                                                                                                                                                                                                                                                                                                                                                                                             |
| Unrestricted Access to Sensitive Business Flows | [Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/), [Bot Management](https://developers.cloudflare.com/bots/), [GraphQL Query Protection](https://developers.cloudflare.com/api-shield/security/graphql-protection/)                                                                                                                                                                                                                                                                                                                                |
| Server Side Request Forgery                     | [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), [WAF managed rules](https://developers.cloudflare.com/waf/managed-rules/), [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/)                                                                                                                                                                                                                                                                                                                                                  |
| Security Misconfiguration                       | [Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/), [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), [WAF managed rules](https://developers.cloudflare.com/waf/managed-rules/), [GraphQL Query Protection](https://developers.cloudflare.com/api-shield/security/graphql-protection/)                                                                                                                                                                                                                 |
| Improper Inventory Management                   | [Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/), [Schema learning](https://developers.cloudflare.com/api-shield/management-and-monitoring/#endpoint-schema-learning)                                                                                                                                                                                                                                                                                                                                                                                             |
| Unsafe Consumption of APIs                      | [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/), [WAF managed rules](https://developers.cloudflare.com/waf/managed-rules/)                                                                                                                                                                                                                                                                                                                                                                                                                                 |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}}]}
```

---

---
title: API Discovery
description: Map out and understand your API attack surface with API Discovery.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# API Discovery

Most development teams struggle to keep track of their APIs. Cloudflare API Discovery helps you map out and understand your API attack surface — the full set of endpoints that could be targeted by attackers.

## Process

Cloudflare produces a map of API endpoints by grouping similar request paths together (path normalization).

For example, you might have thousands of APIs, but a lot of the calls look similar, such as:

* `api.example.com/profile/238`
* `api.example.com/profile/392`

Both paths serve a similar purpose — retrieving user profiles — but they are not identical. To simplify your endpoints, these examples might both map to `api.example.com/profile/*`.

API Discovery runs this process across all your traffic, generating a simple map of endpoints that might look like:

```

/api/login/{customer_identifier}

/api/auth

/api/account/{customer_identifier}

/api/password_reset

/api/logout


```

Similarly, if you have multiple subdomains that share the same set of endpoints, Cloudflare consolidates subdomains:

```

us-api.example.com/api/v1/users/{var1}

de-api.example.com/api/v1/users/{var1}

fr-api.example.com/api/v1/users/{var1}

jp-api.example.com/api/v1/users/{var1}


```

Cloudflare consolidates these to `{hostVar1}.example.com/api/v1/users/{var1}`.

For more technical details, refer to the [blog post ↗](https://blog.cloudflare.com/ml-api-discovery-and-schema-learning/).

### Inbox view

API Shield first catalogs your discovered API endpoints in an inbox-style view. From API Discovery, you can save endpoints to [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/) or ignore endpoints to remove them from view.

Save all discovered API endpoints to Endpoint Management. Ignore any false positives by selecting **Save** or **Ignore** on each line, or use bulk selection.

To get started, search for `var1` in the search box to find all endpoints with path variables and save them first. You can examine endpoints without path variables later.

Adding endpoints to Endpoint Management unlocks additional [security](https://developers.cloudflare.com/api-shield/security/), [visibility](https://developers.cloudflare.com/api-shield/management-and-monitoring/#endpoint-analysis), and [management](https://developers.cloudflare.com/api-shield/management-and-monitoring/) features.

To restore any errantly ignored endpoints, you can filter by **Ignored** and select **Restore**.

API Discovery is an ongoing process. Check back regularly for new results — a badge in the dashboard shows how many endpoints need review.

The **Needs Review** and **Ignored** counts may change over time as your API or traffic patterns change. Discovery results that are not saved can disappear.

Note

Cloudflare will use your feedback on ignored endpoints to improve the API Discovery machine learning model in a future release.

### Machine learning-based discovery

Your API endpoints are discovered with both session identifier-based discovery and machine learning-based discovery.

To access machine learning-based discovery:

* [  New dashboard ](#tab-panel-6559)
* [ Old dashboard ](#tab-panel-6560)

1. In the Cloudflare dashboard, go to the **Web Assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Discovery** tab.
3. Filter the source results by `Session Identifier` or `Machine Learning` to view results from each discovery method.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **API Shield** \> **Discovery**.
3. Filter the source results by `Session Identifier` or `Machine Learning` to view results from each discovery method.

If all of your zone's API traffic contains the session identifier that you have configured, both sources may deliver the same results due to similarities between their underlying methodology. Machine learning-based discovery can identify API traffic regardless of whether your API uses a session identifier.

You can direct any feedback about your API Discovery results to your account team.

## Requirements

To ensure your API endpoints are successfully discovered and mapped by Cloudflare, traffic to the endpoint must meet specific operational criteria.

If an endpoint does not appear in the Discovery inbox, it is typically because the system has not observed enough valid requests over a continuous period. API Discovery only processes requests that satisfy all of the following requirements:

* The request must return a `2xx` response code from the Cloudflare edge.
* The request must not come directly from Cloudflare Workers.
* The endpoint must receive at least 500 requests within a 10-day period.

Endpoints discovered using session identifiers will be labeled as such in the Cloudflare dashboard. If the endpoints are not discovered through session identifiers, they will be discovered using machine learning-based [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/).

## Availability

API Discovery is only available for Enterprise customers. If you are an Enterprise customer interested in this product, contact your account team.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/api-discovery/","name":"API Discovery"}}]}
```

---

---
title: Authentication Posture
description: Identify authentication misconfigurations for API endpoints with Authentication Posture.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Authentication Posture

Authentication Posture detects API endpoints with missing or inconsistent authentication and alerts you to potential misconfigurations.

For example, a security team member may expect that their API endpoints `/api/v1/users` and `/api/v1/orders` require authentication. However, bugs in origin API authentication policies can create broken authentication vulnerabilities — allowing unauthenticated access to protected resources. Authentication Posture details the authentication status of successful requests to your API endpoints, alerting to potential misconfigurations.

Consider a typical e-commerce application. Users can browse items and prices without logging in. However, to retrieve order details via `GET /api/v1/orders/{order_id}`, users must log in and pass an Authorization HTTP header with all requests. Cloudflare alerts you via [Security Center Insights](https://developers.cloudflare.com/security/security-insights/) and [Endpoint labels](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/) if successful requests reach this endpoint or any other endpoint without authentication when session identifiers are configured.

## Process

After configuring [session identifiers](https://developers.cloudflare.com/api-shield/get-started/#session-identifiers), API Shield continuously scans your traffic for successful requests without authentication and labels your endpoints on a daily basis. Refer to the table below for the labeling methodology.

| Description                                                                        | 2xx response codes | 4xx, 5xx response codes                               |
| ---------------------------------------------------------------------------------- | ------------------ | ----------------------------------------------------- |
| If all requests are missing authentication, Cloudflare will apply the label:       | cf-missing-auth    | Without successful responses, no label will be added. |
| If only some requests are missing authentication, Cloudflare will apply the label: | cf-mixed-auth      | Without successful responses, no label will be added. |

### Examine an endpoint's authentication details

* [  New dashboard ](#tab-panel-6561)
* [ Old dashboard ](#tab-panel-6562)

1. In the Cloudflare dashboard, go to the **Web Assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Endpoints** tab.
3. Filter your endpoints by the `cf-risk-missing-auth` or `cf-risk-mixed-auth` labels.
4. Select an endpoint to see its authentication posture details on the endpoint details page.
5. Choose between the 24-hour and 7-day view options, and note any authentication changes over time.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **API Shield** \> **Endpoint Management**.
3. Filter Endpoint Management by the `cf-risk-missing-auth` or `cf-risk-mixed-auth` labels.
4. Select an endpoint to see its authentication posture details on the endpoint details page.
5. Choose between the 24-hour and 7-day view options, and note any authentication changes over time.

The main authentication widget displays how many successful requests over the last seven days had session identifiers included with them, and which identifiers were included with the traffic.

The authentication-over-time chart shows a detailed breakdown over time of how clients successfully interacted with your API and which identifiers were used. A large increase in unauthenticated traffic may signal a security incident. Similarly, any successful unauthenticated traffic on an endpoint that is expected to be 100% authenticated can be a cause for concern.

Work with your development team to understand which authentication policies may need to be corrected on your API to stop unauthenticated traffic.

### Stop unauthenticated traffic with Cloudflare

To block unauthenticated requests, create a [custom rule](https://developers.cloudflare.com/waf/custom-rules/) using the `cf.api_gateway.auth_id_present` field. This field evaluates to `true` when the configured API Shield session identifiers are present on a request. You can also match on absence to detect unauthenticated traffic. Add a host and path match to scope the rule to specific endpoints.

## Limitations

Authentication Posture can only apply when customers accurately set up session identifiers in API Shield. Session identifiers must uniquely identify authenticated users of your API. If you are unsure of your API's session identifier, consult with your development team.

## Availability

Authentication Posture is available for all Enterprise customers with an API Shield subscription.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/authentication-posture/","name":"Authentication Posture"}}]}
```

---

---
title: Broken Object Level Authorization vulnerability detection
description: Detect endpoints at risk of Broken Object Level Authorization attacks.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Broken Object Level Authorization vulnerability detection

A Broken Object Level Authorization (BOLA) vulnerability is where an application or API fails to properly verify if a user has permission to access specific data.

Bugs in the application or API allow attackers to bypass authorization checks and access potentially sensitive information by manipulating and iterating through object identifiers (such as user IDs or order IDs).

Vulnerabilities can occur at any time, including in the original application's deployment. However, changes or upgrades to authentication and authorization policies can also introduce these bugs.

BOLA vulnerabilities are as dangerous as an account takeover. Successfully exploiting a BOLA vulnerability allows the attacker to access or change data that they should not have ownership over.

Cloudflare labels endpoints with BOLA risk when it detects two distinct signals common with attacks exploiting BOLA: **Parameter pollution** and **Enumeration**.

## Enumeration

Cloudflare tracks how each session interacts with every endpoint and flags sessions that successfully request significantly more unique data points than the baseline for that endpoint.

Note

Sessions that have more random behavior or repetition have a higher chance of triggering an alert.

The BOLA enumeration label requires an endpoint to have seen at least 10,000 sessions before being eligible for outlier detection.

Enumeration example

**Endpoint**: `GET /api/v1/users/{userId}/credit-cards`

* **Normal behavior**: Users request credit cards using only their own `userId`.
* **Attack behavior**: Attackers request hundreds of `userId` values per session by brute-force iterating through `userIds` found via other methods.
* **Result**: If the origin authorization policy is broken for this endpoint, the attacker gains credit card information on every user account they request it for.

## Parameter pollution

Cloudflare detects successful requests where a parameter value found in an expected location (path, query string, header, or cookie) is duplicated in an unexpected, similar location. This behavior may be indicative of attackers trying to confuse the API's authorization system and bypass security controls.

Parameter pollution example

**Endpoint**: `GET /api/v1/orders/{orderId}`

* **Normal behavior**: `orderId` sent in a path variable like `GET /api/v1/orders/12345`
* **Attacker behavior**: `orderId` is also sent as a query parameter, triggering old, undocumented code that looks for orders in the query parameter and happens to lack an authorization check: `GET /api/v1/orders/12345?orderId=67890`
* **Result**: By passing in a fake order or an order that the attacker owns (`12345`), they are able to trigger the old, undocumented code and access an order that they do not own (`67890`)

## Process

API Shield detects BOLA attacks by learning visitor traffic patterns and identifying anomalous access to specific objects. Affected endpoints are automatically labeled with the following [risk labels](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/#risk-labels):

* `cf-risk-bola-enumeration`: Automatically added when an endpoint experiences successful responses with drastic differences in the number of unique elements requested by different user sessions.
* `cf-risk-bola-pollution`: Automatically added when an endpoint experiences successful responses where parameters are found in multiple places in the request, as opposed to what is expected from the API's schema.

If you see one of these labels on your API endpoints, check its authorization policy with your developer team to find any authorization bugs. You can also contact Cloudflare for a report including attacker identifiers to confirm attack reach and impact.

BOLA attack information can be found in your [Security Overview](#security-overview), [Security Analytics](#security-analytics), and [Endpoint details](#endpoint-details).

### Security Overview

If BOLA vulnerabilities have been detected on your endpoints, you can view a summary of the attack and suggestions to mitigate it via the Cloudflare dashboard.

1. In the Cloudflare dashboard, go to the **Security** page.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/security/overview)
2. Go to **API abuse** or **All suggestions**.
3. Depending on the type of attack, select **Review traffic from potential BOLA enumeration attack** or **Review traffic from potential parameter pollution attack** to view details of the attack and suggested actions.
4. Select **View all affected endpoints** or **View details** on a specific endpoint to review suspicious sessions in [Web Assets](#endpoint-details).

Cloudflare evaluates your session requests for both enumeration and parameter pollution attacks and provides you with a list of at-risk endpoints and the number of anomalous sessions where an attack was detected. You can follow the suggested actions to address your BOLA vulnerabilities and prevent future attacks against your endpoints.

Note

If the insight has been archived but attacks are still present, you can filter by **Show archived**.

### Security Analytics

You can view analytics of your zone's traffic profile and suspicious requests associated with enumeration or parameter pollution attacks in the Cloudflare dashboard.

[ Go to **Analytics** ](https://dash.cloudflare.com/?to=/:account/:zone/security/analytics) 

Filter requests depending on the type of attack detected in your zone, including the hashed session IDs found in the attack and the corresponding BOLA vulnerability risk label, to see an analysis of your request activity from the past seven days. This filter includes all traffic from suspected attacker sessions, so you can evaluate other actions that they are taking against your zone.

This does not filter by specific endpoints.

Review the top statistics and details of managed API endpoints, paths and values targeted by the attack, source IPs, source user agents, and source fingerprints.

Review your traffic profile for unusual patterns, such as spikes in unique object requests or unexpected parameter locations.

### Endpoint details

You can expand the endpoint details in Web Assets to access information on suspicious sessions' activity on the endpoint, including both enumeration attack and parameter pollution attack details.

[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets) 

Under **Security overview**, select **View attack** to review affected sessions with associated IP addresses and JA4 fingerprints (TLS client fingerprints that help identify the software making the request).

You can export the `.csv` file containing all the IP addresses and JA4 fingerprints for all or only a specific session.

Note

The hashed session ID is used for privacy purposes and only as a unique identifier for a specific session. It cannot be un-hashed. It will not match your customer values in your application or database.

The details specify the parameter that was affected, the number of sessions involved in the attack, and how far their behavior deviated from baseline.

If unauthorized access to the parameter was obtained, consider the potential impact to your application, users, and data. As a best practice, consult with your application and API developers to confirm unauthorized access by reviewing your API origin logs for the IP address and JA4 fingerprint of the abusive sessions.

You can view attack data in [Security Analytics](#security-analytics).

[ Go to **Analytics** ](https://dash.cloudflare.com/?to=/:account/:zone/security/analytics) 

The managed endpoint will be automatically filtered in the request activity from the past seven days. You can also filter by suspicious IP addresses and fingerprints found in the attack details.

---

## Availability

Broken Object Level Authorization vulnerability detection is only available for Enterprise customers. If you are an Enterprise customer interested in this product, contact your account team.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/bola-vulnerability-detection/","name":"Broken Object Level Authorization vulnerability detection"}}]}
```

---

---
title: GraphQL malicious query protection
description: Scan GraphQL traffic and block queries that could overload your origin.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# GraphQL malicious query protection

GraphQL is a query language for APIs. In addition to protecting RESTful APIs, Cloudflare can also protect GraphQL APIs.

GraphQL malicious query protection scans your GraphQL traffic for queries that could overload your origin and result in a denial of service. You can build rules that limit the query depth and size of incoming GraphQL queries in order to block suspiciously large or complex queries.

## Availability

GraphQL malicious query protection is available for all API Shield customers. Enterprise customers who have not purchased API Shield can preview [API Shield as a non-contract service ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/api-shield) in the Cloudflare dashboard or by contacting your account team.

## Limitations

The following limitations apply:

* Parsing is limited to GraphQL `POST` bodies smaller than 20 KB. This limit will be raised in a future release.
* Only `POST` requests with content types of `application/json` or `application/graphql` are inspected.
* Queries containing fragments or multiple operations are not supported.
* Parsing and rules are limited to paths ending in `/graphql`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/graphql-protection/","name":"GraphQL malicious query protection"}}]}
```

---

---
title: Configure GraphQL malicious query protection via the API
description: Use the GraphQL API to configure query size and depth limits for your API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configure GraphQL malicious query protection via the API

Use the [Cloudflare GraphQL API](https://developers.cloudflare.com/analytics/graphql-api/getting-started/) to gather data about your GraphQL API’s current usage and configure Cloudflare’s GraphQL malicious query protection to log or block malicious queries.

## Introduction

Query size is defined as the number of terminal fields (leaves) in the query, whereas query depth is the deepest level at which a leaf is present. For example, the size of this query will be reported as `4 (terminalField[1-4] all contribute to this counter)`, and the depth will be reported as `3 (terminalField3 and terminalField4 are at depth level 3)`.

GraphQL query

```

{

  terminalField1

  nonTerminalField1(filter: 123) {

    terminalField2

    nonTerminalField2 {

      terminalField3

      terminalField4

    }

  }

}


```

## Gather GraphQL statistics

Using the new `apiGatewayGraphqlQueryAnalyticsGroups` node in the Cloudflare GraphQL API, you can retrieve `apiGatewayGraphqlQuerySize` and `apiGatewayGraphqlQueryDepth` dimensions.

GraphQL query

```

query ApiGatewayGraphqlQueryAnalytics(

  $zoneTag: string

  $start: Time

  $end: Time

) {

  viewer {

    zones(filter: { zoneTag: $zoneTag }) {

      apiGatewayGraphqlQueryAnalyticsGroups(

        limit: 100

        orderBy: [

          apiGatewayGraphqlQuerySize_DESC

          apiGatewayGraphqlQueryDepth_DESC

        ]

        filter: { datetime_geq: $start, datetime_leq: $end }

      ) {

        count

        dimensions {

          apiGatewayGraphqlQuerySize

          apiGatewayGraphqlQueryDepth

        }

      }

    }

  }

}


```

[Run in GraphQL API Explorer](https://graphql.cloudflare.com/explorer?query=I4VwpgTgngBAggBwJYHECGAXMB3NUURoIAWwANgIrjRwB2aZUGSAxgM4AUAUDDACQAvAPa0wAFTQBzAFww2GCElqSe-eWggZZYpAFswqvmFoATbXoMBKGAG9VANyQ5It1b2GjOAMyRksEWRsYD3EpWUERUMkYAF9rO15EmCJUTBw8AiJSSmooOgYmVjYCIRAETjckmDI9JC0YAEYABibKpKEIE0gAIShZAG02qpT0LFx8QhJyKkgoAGUkATAAfQARAFE5gGEhpJG08cypnNnVsAQMYjXNnarEgF1dmB8-SECYEzTmfWXJMGBwupNAAaD5fCzLMj-cLGEyxIbxJ4sUq0DBPEwWWhsJAiNiuO57ZCjdITLLTXILJZPXj7MYZSbZGbQM4XYhPGJDDlJLnwmJAA&variables=N4IgXg9gdgpgKgQwOYgFwgFoHkByBRAfQEkAREAGhAGcAXBAJxrRACYAGFgNgFo2eBGFnH4BWVGwCcqACwBmDBRAwoAE2bsuvAUJb9xUuQoC+QA)

With the above query, you will get the following response:

Response

```

{

  "data": {

    "viewer": {

      "zones": [

        {

          "apiGatewayGraphqlQueryAnalyticsGroups": [

            {

              "count": 10,

              "dimensions": {

                "apiGatewayGraphqlQueryDepth": 1,

                "apiGatewayGraphqlQuerySize": 11

              }

            },

            {

              "count": 10,

              "dimensions": {

                "apiGatewayGraphqlQueryDepth": 1,

                "apiGatewayGraphqlQuerySize": 2

              }

            }

          ]

        }

      ]

    }

  },

  "errors": null

}


```

In the response example, Cloudflare observed 10 requests with depth 1 and size 11, and 10 requests with depth 1 and size 2 in the selected timeframe.

## Analyze GraphQL statistics

You can use the response to compute percentiles across the attributes and set a threshold on what is allowed. For example, you can use a simple heuristic like `1.5 * p99` for query size or depth.

Here is a simple Python script that will report query size and depth p-levels given the GraphQL API response output above (as a JSON file):

Python script

```

#!/usr/bin/env python3


import json

import numpy as np

import argparse


parser = argparse.ArgumentParser()

parser.add_argument("--response", help="Path to the API JSON response file with the apiGatewayGraphqlQueryAnalyticsGroups node", required=True)

args = parser.parse_args()

with open(args.response) as f:

    query_sizes = np.array([], dtype=np.uint16)

    query_depths = np.array([], dtype=np.uint8)

    data = json.load(f)['data']['viewer']['zones'][0]['apiGatewayGraphqlQueryAnalyticsGroups']

    for datapoint in data:

        query_sizes = np.append(query_sizes, [datapoint['dimensions']['apiGatewayGraphqlQuerySize']] * datapoint['count'])

        query_depths = np.append(query_depths, [datapoint['dimensions']['apiGatewayGraphqlQueryDepth']] * datapoint['count'])


    quantiles = [0.99, 0.95, 0.75, 0.5]

    print('\n'.join([f"Query size {int(q * 100)}th percentile is {v}" for q, v in zip(quantiles, np.quantile(query_sizes, quantiles))]))

    print('\n'.join([f"Query depth {int(q * 100)}th percentile is {v}" for q, v in zip(quantiles, np.quantile(query_depths, quantiles))]))


```

With the above query, you will get the following output:

```

./calculator.py --response=response.json

Query size 99th percentile is 11.0

Query size 95th percentile is 11.0

Query size 75th percentile is 11.0

Query size 50th percentile is 6.5

Query depth 99th percentile is 1.0

Query depth 95th percentile is 1.0

Query depth 75th percentile is 1.0

Query depth 50th percentile is 1.0


```

## Set limits on incoming GraphQL queries

API Shield customers now have three new fields available in custom rules:

* `cf.api_gateway.graphql.query_size` describes the size of a GraphQL query.
* `cf.api_gateway.graphql.query_depth` describes the depth of a GraphQL query.
* `cf.api_gateway.graphql.parsed_successfully` describes whether Cloudflare was able to parse the query. Presently, we run best-effort parsing, meaning we might not be able to parse some valid queries. This means that you must use a `and cf.api_gateway.graphql.parsed_successfully` filter in your custom rules when deploying GraphQL security rules.

For example, you can deploy the following rule via the API or the dashboard to block queries that are deeply nested and ask for over 30 fields.

```

(cf.api_gateway.graphql.query_size > 30 and cf.api_gateway.graphql.query_depth > 7 and cf.api_gateway.graphql.parsed_successfully)


```

Note

You are not able to configure which endpoints the GraphQL parsing runs on. Requests are parsed if they are targeting a path ending in `/graphql`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/graphql-protection/","name":"GraphQL malicious query protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/api-shield/security/graphql-protection/api/","name":"Configure GraphQL malicious query protection via the API"}}]}
```

---

---
title: JSON Web Tokens validation
description: Verify incoming JWTs to prevent replay attacks and token tampering at the edge.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# JSON Web Tokens validation

JSON web tokens (JWT) are often used as part of an authentication component on many web applications. Since JWTs are crucial to identifying users and their access, ensuring the token’s integrity is important.

API Shield’s JWT validation stops JWT replay attacks and JWT tampering by cryptographically verifying incoming JWTs before they are passed to your API origin. JWT validation will also stop requests with expired tokens or tokens that are not yet valid.

## Process

Endpoints must be added to [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/) for JWT validation to protect them.

A JWT validation configuration has two parts: a token validation configuration that contains your JWT signer's public JSON Web Key Set (JWKS), and a JWT validation rule that specifies which hostnames and endpoints to validate.

### Add a token validation configuration

* [  New dashboard ](#tab-panel-6563)
* [ Old dashboard ](#tab-panel-6564)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **API abuse**.
3. On **Token configurations**, select **Configure tokens**.
4. Add a name for your configuration.
5. Choose where Cloudflare can locate the JWT for this configuration on incoming requests, such as a header or cookie and its name.
6. Copy and paste your JWT issuer's public key(s) (JWKS).

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/login), and select your account and domain.
2. Go to **Security** \> **API Shield** \> **Settings**.
3. Under **JSON Web Token Settings**, select **Add configuration**.
4. Add a name for your configuration.
5. Choose where Cloudflare can locate the JWT for this configuration on incoming requests, such as a header or cookie and its name.
6. Copy and paste your JWT issuer's public key(s) (JWKS).

Each JWT issuer typically publishes public keys (JWKS) for verification at a known URL on the Internet. If you do not know where to get them, contact your identity administrator.

To automatically keep your JWKS up to date when your identity provider refreshes them, you can use a Worker. Refer to [Configure Workers to automatically update keys](https://developers.cloudflare.com/api-shield/security/jwt-validation/jwt-worker/) to learn more about setting up the Worker.

### Add a JWT validation rule

* [  New dashboard ](#tab-panel-6565)
* [ Old dashboard ](#tab-panel-6566)

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. On API JWT validation rules, select **Create rule**.
3. Add a name for your rule.
4. Select a hostname to protect requests with saved endpoints using the rule.
5. Deselect any endpoints that you want JWT validation to ignore (for example, an endpoint used to generate a JWT).
6. Select the token validation configuration that corresponds to the incoming requests.
7. Choose whether to strictly enforce token presence on these endpoints.  
   * You may not expect 100% of clients to send in JWTs with their requests. If this is the case, choose _Ignore_. JWT validation will still validate JWTs that are present.  
   * You may otherwise expect all requests to the selected hostname and endpoints to contain JWTs. If this is the case, choose _Mark as non-compliant_.
8. Choose an action to take for non-compliant requests. For example, JWTs that do not pass validation (expired, tampered with, or bad signature tokens) or requests with missing JWTs when _Mark as non-compliant_ is selected in the previous step.
9. Select **Save**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/login), and select your account and domain.
2. Go to **Security** \> **API Shield** \> **API Rules**.
3. Add a name for your rule.
4. Select a hostname to protect requests with saved endpoints using the rule.
5. Deselect any endpoints that you want JWT validation to ignore (for example, an endpoint used to generate a JWT).
6. Select the token validation configuration that corresponds to the incoming requests.
7. Choose whether to strictly enforce token presence on these endpoints.  
   * You may not expect 100% of clients to send in JWTs with their requests. If this is the case, choose _Ignore_. JWT validation will still validate JWTs that are present.  
   * You may otherwise expect all requests to the selected hostname and endpoints to contain JWTs. If this is the case, choose _Mark as non-compliant_.
8. Choose an action to take for non-compliant requests. For example, JWTs that do not pass validation (expired, tampered with, or bad signature tokens) or requests with missing JWTs when _Mark as non-compliant_ is selected in the previous step.
9. Select **Save**.

Note

Token configuration rules will automatically apply to new endpoints added to Endpoint Management if those endpoints also match the rule.

---

## Special cases

### Validate two JWTs with different identity providers on a single request

If you expect that two different JWTs should be present in a request and you want to validate both, you must create two different token configurations. When selecting the two configurations in your validation rule, select _Validate all configurations_ under **Validation behavior for multiple configurations**.

### Support a migration from one identity provider to another

If you expect to migrate between two different identity providers, you must create two different token configurations and two different validation rules, each corresponding to its own configuration. With this setup, you can change the action for different validation rules depending on the state of your migration.

### JSON Web Tokens with the `Bearer` prefix

API Shield will verify JSON Web Tokens regardless of whether they have the `Bearer` prefix.

### Rate limit by user (JWT claim)

You can rate limit requests based on any claim inside of a JSON Web Token (JWT), such as:

* Registered claims like `aud` or `sub`
* Custom claims like `userEmail`, including nested custom claims like `user.email`

Rate limiting based on JWT claim values will only work on valid JSON Web Tokens. If you do not block invalid JSON Web Tokens on your path, the [JWT claims will all be counted and possibly blocked](https://developers.cloudflare.com/waf/rate-limiting-rules/parameters/#missing-field-versus-empty-value) if high traffic is detected in the Point of Presence (PoP).

You must also count the JWT claim that uniquely identifies the user. If you select a claim that is the same for many of your users, their rate limits will all be counted together.

### Rate limit by user tier

If you offer multiple tiers on your website or application and you want to enforce rate limiting based on the tiers, such as:

* If `"aud": "free-tier"`, rate limit to five requests per minute.
* If `"aud": "premium-tier"`, rate limit to 50 requests per minute.

You can follow the rate limiting rule example below:

Example rule expression

```

(http.request.method eq "GET" and

http.host eq "<YOUR_DOMAIN>" and

http.request.uri.path matches "</EXAMPLE_PATH>" and

lookup_json_string(http.request.jwt.claims["<JWT_TOKEN_CONFIGURATION_ID>"][0], "aud") eq "free-tier"


```

### Ignore `OPTIONS` pre-flight CORS requests

Due to cross-origin resource sharing (CORS) security, web browsers will send "pre-flight" requests using the `OPTIONS` verb to API endpoints before sending a `GET` (or other verb) request. By definition, `OPTIONS` preflight requests do not include credentials (authentication headers or cookies) and are anonymous.

If you expect web browsers to be valid clients of your API, and to prevent blocking `OPTIONS` requests from those browsers, Cloudflare recommends adding `or http.request.method eq "OPTIONS"` to your JWT validation rules.

---

## Availability

JWT validation is available for all API Shield customers. Enterprise customers who have not purchased API Shield can preview [API Shield as a non-contract service ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/api-shield) in the Cloudflare dashboard or by contacting your account team.

---

## Limitations

Currently, the following known limitations exist:

1. JWT validation only operates on JWTs sent in client request headers or cookies. If your clients send in JWTs in a `POST` body, direct that feedback to your account team.
2. JWT validation only operates for endpoints (host, method, and path) added to Endpoint Management. You can add all of your endpoints to endpoint management through [API Discovery](https://developers.cloudflare.com/api-shield/management-and-monitoring/#add-endpoints-from-api-discovery), [Schema validation](https://developers.cloudflare.com/api-shield/management-and-monitoring/#add-endpoints-from-schema-validation), [manually via the Cloudflare dashboard](https://developers.cloudflare.com/api-shield/management-and-monitoring/#add-endpoints-manually), or via the [API](https://developers.cloudflare.com/api/resources/api%5Fgateway/subresources/operations/methods/create/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/jwt-validation/","name":"JSON Web Tokens validation"}}]}
```

---

---
title: Configure JWT validation via the API
description: Create token configurations and validation rules for JWT validation using the API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configure JWT validation via the API

Use the Cloudflare API to configure [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/), which requires token configurations and token validation rules.

## Token configurations

A token configuration defines a JSON Web Key Set (JWKs), which is used to validate JSON Web Tokens (JWTs) sent by clients and information on where these JWTs are sent in the request.

Note

A zone may have up to four token configurations.

Token configurations require the following information:

| Field name     | Description                                                                                                                                                 | Example                                                                                                             | Notes                                             |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
| title          | A human-readable name for the configuration that allows you to quickly identify the purpose of the configuration.                                           | Production JWT configuration                                                                                        | Limited to 50 characters.                         |
| description    | A human-readable description that gives more details than title which serves as a means to allow customers to better document the use of the configuration. | This configuration is used for all endpoints in endpoint management and checks the JWT in the authorization header. | Limited to 500 characters.                        |
| token\_sources | A list of possible locations where then JWT can be found on the request.                                                                                    | http.request.headers\[\\"authorization\\"\]\[0\] http.request.cookies\[\\"Authorization\\"\]\[0\]                   | Refer to the [information](#token-sources) below. |
| token\_type    | This specifies the type of token to validate.                                                                                                               | jwt                                                                                                                 | Only jwt is currently supported.                  |
| credentials    | This describes the cryptographic public keys that should be used to validate JWTs. This field must be a JSON web key.                                       | Refer to the example below.                                                                                         | Refer to the [information](#credentials) below.   |

### Token sources

Each item must be a Ruleset Engine expression that resolves to a string.

Currently supported fields are `http.request.headers` and `http.request.cookies`.

You can set up to four token sources. If a request has more than one of these fields set, only one will be used. Leading `Bearer: ` strings in request tokens are automatically ignored.

Refer to the [Ruleset Engine documentation](https://developers.cloudflare.com/ruleset-engine/rules-language/fields) for details on working with Ruleset Engine fields.

### Credentials

API Shield supports credentials of type `RS256`, `RS384`, `RS512`, `PS256`, `PS384`, `PS512`, `ES256`, and `ES384`. RSA keys must be at least 2048-bit. Each JSON web key must have a “KID” which must be present in the JWT's header as well to allow API Shield to match them.

We allow up to 4 different keys in order to aid in key rollover.

Cloudflare will remove any fields that are unnecessary from each key and will drop keys that we do not support.

It is highly recommended to validate the output of the API call to check that the resulting keys appear as intended.

## Token configuration JSON object

The example below shows a JSON object with all of the information necessary to create a token configuration using the Cloudflare API. If you would like to create JWKs for testing, refer to [mkjwk JSON Web Key Generator ↗](https://mkjwk.org/).

Example

```

{

  "title": "Production JWT configuration",

  "description": "This configuration checks the JWT in the authorization header or cookie.",

  "token_sources": [

    "http.request.headers[\"authorization\"][0]",

    "http.request.cookies[\"Authorization\"][0]"

  ],

  "token_type": "jwt",

  "credentials": {

    "keys": [

      {

        "kty": "EC",

        "use": "sig",

        "crv": "P-256",

        "kid": "93UrzmNu1mqXs5cZcvCPkTlMHB2Jya30vSTkiBb0vhU",

        "x": "QG3VFVwUX4IatQvBy7sqBvvmticCZ-eX5-nbtGKBOfI",

        "y": "A3PXCshn7XcG7Ivvd2K_DerW4LHAlIVKdqhrUnczTD0",

        "alg": "ES256"

      }

    ]

  }

}


```

## Create a token configuration using the Cloudflare API

Use cURL or any other API client tool to send the new configuration to Cloudflare’s API to enable JWT validation. Make sure to replace `{zone_id}` with the relevant zone ID and add your [authentication credentials](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) header.

Example using cURL

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/config" \

--header 'Content-Type: application/json' \

--data '{

    "title": "Production JWT configuration",

    "description": "This configuration checks the JWT in the authorization header or cookie.",

    "token_sources": [

        "http.request.headers[\"authorization\"][0]",

        "http.request.cookies[\"Authorization\"][0]"

    ],

    "token_type": "jwt",

    "credentials": {

        "keys": [

            {

                "kty": "EC",

                "use": "sig",

                "crv": "P-256",

                "kid": "93UrzmNu1mqXs5cZcvCPkTlMHB2Jya30vSTkiBb0vhU",

                "x": "QG3VFVwUX4IatQvBy7sqBvvmticCZ-eX5-nbtGKBOfI",

                "y": "A3PXCshn7XcG7Ivvd2K_DerW4LHAlIVKdqhrUnczTD0",

                "alg": "ES256"

            }

        ]

    }

}'


```

The response will be in a Cloudflare `v4` response envelope and the result contains the created configuration. Note the returned ID, as it will be used to reference the token configuration when creating token validation rules using the API.

Example response

```

{

  "result": {

    "id": "d5902294-00c3-4aed-b517-57e752e9cd58",

    "token_type": "JWT",

    "title": "Production JWT configuration",

    "description": "This configuration checks the JWT in the authorization header or cookie.",

    "token_sources": [

      "http.request.headers[\"authorization\"][0]",

      "http.request.cookies[\"Authorization\"][0]"

    ],

    "credentials": {

      "keys": [

        {

          "x": "QG3VFVwUX4IatQvBy7sqBvvmticCZ-eX5-nbtGKBOfI",

          "y": "A3PXCshn7XcG7Ivvd2K_DerW4LHAlIVKdqhrUnczTD0",

          "alg": "ES256",

          "crv": "P-256",

          "kid": "93UrzmNu1mqXs5cZcvCPkTlMHB2Jya30vSTkiBb0vhU",

          "kty": "EC"

        }

      ]

    },

    "created_at": "2023-11-08T16:45:17.236841Z",

    "last_updated": "2023-11-08T16:45:17.236841Z"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

## Token validation rules

Token validation rules allow you to enforce a security policy using existing token configurations.

Token validation rules can be configured using the Cloudflare API or [dashboard](https://developers.cloudflare.com/api-shield/security/jwt-validation/#add-a-jwt-validation-rule).

| Field name  | Description                                                                               | Example                                                                      | Notes                                                                                                                                               |
| ----------- | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| title       | A human-readable name allowing you to quickly identify it.                                | JWT validation on v1 and v2.example.com                                      | Limited to 50 characters.                                                                                                                           |
| description | A human-readable description that gives more details than title and helps to document it. | Log requests without a valid authorization header.                           | Limited to 500 characters.                                                                                                                          |
| action      | The Firewall Action taken on requests that do not meet expression.                        | log                                                                          | Possible: log or block                                                                                                                              |
| enabled     | Enable or disable the rule.                                                               | true                                                                         | Possible: true or false                                                                                                                             |
| expression  | The rule's security policy.                                                               | is\_jwt\_valid ("00170473-ec24-410e-968a-9905cf0a7d03")                      | Make sure to escape any quotes when creating rules using the Cloudflare API.  Refer to [Define a security policy](#define-a-security-policy) below. |
| selector    | Configure what operations are covered by this rule.                                       | Refer to [Applying a rule to operations](#apply-a-rule-to-operations) below. |                                                                                                                                                     |

### Selectors

Selectors control the scope of your token validation rule.

If you only need JWT validation on specific hostnames or subdomains of your apex domain, use the hostname in a selector to include it in the JWT validation rule.

If you need to exclude endpoints from JWT validation that never have valid JWTs used with them (by design), such as a path and method used to establish a valid JWT in the first place, you must use the endpoint’s operation ID to exclude the endpoint in a selector.

To find the operation ID, refer to [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/) or use the [Cloudflare API](https://developers.cloudflare.com/api/resources/api%5Fgateway/subresources/operations/methods/list/).

## Define a security policy

Note

A request must also match an operation covered by this rule to trigger an action.

Refer to [Apply a rule to operations](#apply-a-rule-to-operations) for more information.

A token validation rule's expression defines a security policy that a request must meet.

For example, the expression `is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e") or is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e")` will trigger if an incoming request does not have at least one valid authentication token.

These expressions are similar to [expressions used in Ruleset Engine](https://developers.cloudflare.com/ruleset-engine/rules-language/), with a few key differences:

* The token validation rule actions trigger if the expression evaluates `false`, as opposed to Ruleset expressions.
* The token validation rules can use dedicated functions that reference token configurations.

Operators such as `or`, `and`, `eq`, and more are usable in expressions in the same way as in expressions used in Ruleset Engine.

The following functions can be used to interact with JWT Tokens on a request:

* [is\_jwt\_valid(token\_configuration\_id)](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#is%5Fjwt%5Fvalid) — Returns true if the request has a valid token according to the token configuration with the ID `token_configuration_id`.
* [is\_jwt\_present(token\_configuration\_id)](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#is%5Fjwt%5Fpresent) — Returns true if the request has a token as configured in the token configuration with the ID `token_configuration_id`.

### Common use cases

Refer to the following example use cases to understand which security policy to use. For most use cases, Cloudflare recommends requiring a valid token across your API and excluding any paths that are used to establish or refresh tokens using selectors.

#### Require a token

The `is_jwt_present("51231d16-01f1-48e3-93f8-91c99e81288e")` expression will trigger an action if a request is missing a JWT.

It can be combined with a `log` action in the token validation rule to log requests that are missing an authentication header.

#### Require a valid token

The `is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e")` expression will trigger an action if a request does not have a valid JWT.

It can be combined with a `block` action in the token validation rule to block requests with no or invalid credentials.

#### Require at least one of two possible tokens

The `is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e") or is_jwt_valid("fddfc39e-3686-4683-ab23-bf917da6bb43")` expressions will trigger an action if a request does not have at least one valid token.

This can occur if you need to split JWKs into multiple token configurations.

#### Require a valid token but ignore requests without a token

The `is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e") or not is_jwt_present("51231d16-01f1-48e3-93f8-91c99e81288e")` expressions will trigger an action if a request has an invalid token, ignoring requests with no tokens at all.

## Apply a rule to operations

Only one token validation rule can apply to an operation. If an operation is covered by multiple rules, then the rule with highest precedence will take effect.

You can configure which operations JWT validation is enforced on using the `selector` field.

Note

Selectors will also apply to new operations. New operations that match an existing selector will automatically be covered by that token validation rule.

For example, the following selector will apply a rule to all operations in `v1.example.com` and `v2.example.com`, except for two operations on these hosts:

Selector example

```

{

  "include": [

    {

      "host": ["v1.example.com", "v2.example.com"]

    }

  ],

  "exclude": [

    {

      "operation_ids": [

        "f9c5615e-fe15-48ce-bec6-cfc1946f1bec", // POST v1.example.com/login

        "56828eae-035a-4396-ba07-51c66d680a04" // POST v2.example.com/login

      ]

    }

  ]

}


```

Operations can be included at a host level and ignored on a per-operation basis.

You can use the `POST /zones/{zone_id}/token_validation/rules/preview` endpoint to see the operations covered by this rule:

Example using cURL

```

curl --request PUT \

'https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/preview' \

--header 'Content-Type: application/json' \

--data '{

    "include": [

        {

            "host": [

                "v1.example.com",

                "v2.example.com"

            ]

        }

    ],

    "exclude": [

        {

            "operation_ids": [

                "f9c5615e-fe15-48ce-bec6-cfc1946f1bec", // POST v1.example.com/login

                "56828eae-035a-4396-ba07-51c66d680a04"  // POST v2.example.com/login

            ]

        }

    ]

}'


```

The response will include all operations on a zone with an additional `state` field.

The `state` field can be `ignored`, `excluded`, or `included`. Included operations will match the hostname selectors you specified. Excluded operations will match the operation IDs you specified in the selector. Ignored operations are those that do not match anything specified in the selector.

Result

```

{

  "result": {

    "operations": [

      {

        "operation_id": "ed15fcb6-5a73-41cd-91af-8c61e5bb1cdb",

        "method": "GET",

        "host": "example.com",

        "endpoint": "/api/accounts/{var1}",

        "last_updated": "2023-05-24T14:54:34.806506Z",

        "state": "ignored"

      },

      {

        "operation_id": "e7a582cd-3cfb-4061-ab5b-722e6e42f545",

        "method": "GET",

        "host": "v1.example.com",

        "endpoint": "/api/accounts/{var1}",

        "last_updated": "2023-05-24T14:54:34.806506Z",

        "state": "included"

      },

      {

        "operation_id": "ddd5df5a-795c-40ce-b38c-38e9d7ef9ae8",

        "method": "GET",

        "host": "v2.example.com",

        "endpoint": "/api/accounts/{var1}",

        "last_updated": "2023-05-24T14:54:34.806506Z",

        "state": "included"

      },

      {

        "operation_id": "4d20befb-0120-45d5-9b29-5835fd41b44e",

        "method": "GET",

        "host": "v3.example.com",

        "endpoint": "/api/accounts/{var1}",

        "last_updated": "2023-05-24T14:54:34.806506Z",

        "state": "ignored"

      },

      {

        "operation_id": "f9c5615e-fe15-48ce-bec6-cfc1946f1bec",

        "method": "POST",

        "host": "v1.example.com",

        "endpoint": "/login",

        "last_updated": "2023-05-24T14:54:34.806506Z",

        "state": "excluded"

      },

      {

        "operation_id": "56828eae-035a-4396-ba07-51c66d680a04",

        "method": "POST",

        "host": "v2.example.com",

        "endpoint": "/login",

        "last_updated": "2023-05-24T14:54:34.806506Z",

        "state": "excluded"

      },

      {

        "operation_id": "cf86874c-8d0c-4337-ae14-4e2459b541ac",

        "method": "GET",

        "host": "v3.example.com",

        "endpoint": "login",

        "last_updated": "2023-05-24T14:54:34.806506Z",

        "state": "ignored"

      }

    ],

    "total": 7,

    "included": 2,

    "excluded": 2,

    "ignored": 3,

    "selected_hosts": ["v1.example.com", "v2.example.com"],

    "available_hosts": [

      "example.com",

      "v1.example.com",

      "v1.example.com",

      "v3.example.com"

    ]

  },

  "success": true,

  "errors": [],

  "messages": [],

  "result_info": {

    "page": 1,

    "per_page": 20,

    "count": 20,

    "total_count": 1631

  }

}


```

Operations with a `included` state will be covered by the token validation rule. The response also shows the hostnames of included operations in `result.selected_hosts` and shows all hostnames used by all zone operations in `result.available_hosts`.

You can also send an empty object in the request body:

Example using cURL

```

curl --request PUT \

'https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/preview' \

--header 'Content-Type: application/json' \

--data '{ }'


```

The response will show all zone operations and all possible hosts, which you can use to build your own selector.

## Token validation rule JSON object

The example below shows a JSON object with all the necessary information to create a token validation rule using the Cloudflare API.

Replace any token configurations IDs and operation IDs with the IDs that exist in your zone.

Token Validation Rule JSON example

```

[

  {

    "title": "JWT Validation on v1 and v2.example.com",

    "description": "Log requests without a valid authorization header.",

    "action": "log",

    "enabled": true,

    "expression": "is_jwt_valid(\"00170473-ec24-410e-968a-9905cf0a7d03\")",

    "selector": {

      "include": [

        {

          "host": ["v1.example.com", "v2.example.com"]

        }

      ],

      "exclude": [

        {

          "operation_ids": [

            "f9c5615e-fe15-48ce-bec6-cfc1946f1bec",

            "56828eae-035a-4396-ba07-51c66d680a04"

          ]

        }

      ]

    }

  }

]


```

## Create a token Validation rule using the Cloudflare API

Use cURL or any other API client tool to send the new configuration to Cloudflare's API to enable JWT validation. Make sure to replace `{zone_id}` with the relevant zone ID and add your [authentication credentials](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) header.

Replace any token configurations IDs and operation IDs with the IDs that exist in your zone.

A single request can create multiple rules. To do so, pass multiple rule objects in the JSON array of the request body.

Example using cURL

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/bulk" \

--header 'Content-Type: application/json' \

--data '[

    {

        "title": "JWT Validation on v1 and v2.example.com",

        "description": "Log requests without a valid authorization header.",

        "action": "log",

        "enabled": true,

        "expression": "is_jwt_valid(\"00170473-ec24-410e-968a-9905cf0a7d03\")",

        "selector": {

            "include": [

                {

                    "host": [

                        "v1.example.com",

                        "v2.example.com"

                    ]

                }

            ],

            "exclude": [

                {

                    "operation_ids": [

                        "f9c5615e-fe15-48ce-bec6-cfc1946f1bec",

                        "56828eae-035a-4396-ba07-51c66d680a04"

                    ]

                }

            ]

        }

    }

]'


```

The response will be in a Cloudflare `v4` response envelope and the result contains the created rules. Note the returned ID for each rule, which can be used to edit or delete an existing rule.

Result

```

{

  "result": [

    {

      "id": "5ec7c417-6964-4b24-b82c-a23a7ec8f90c",

      "title": "JWT Validation on v1 and v2.example.com",

      "description": "Log requests without a valid authorization header.",

      "action": "log",

      "enabled": true,

      "expression": "is_jwt_valid(\"00170473-ec24-410e-968a-9905cf0a7d03\")",

      "selector": {

        "include": [

          {

            "host": ["v1.example.com", "v2.example.com"]

          }

        ],

        "exclude": [

          {

            "operation_ids": [

              "f9c5615e-fe15-48ce-bec6-cfc1946f1bec",

              "56828eae-035a-4396-ba07-51c66d680a04"

            ]

          }

        ]

      },

      "created_at": "2023-10-18T12:08:09.575388Z",

      "last_updated": "2023-10-18T12:08:09.575388Z",

      "modified_by": "user@cloudflare.com"

    }

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

## Maintenance

### Update token configuration

It is best practice to rotate keys after some time. To support updating the keys, Cloudflare allows up to four keys per configuration. This allows you to add a second, new key to an already existing key. You can start issuing JWTs with the new key only and remove the old key after some time. Additionally, this feature allows the deployment of testing or development keys next to production keys.

The input to updating the keys is the same as when creating a configuration where you supplied the initial keys using the credentials key and needs to be a JWK.

Note

Cloudflare will remove any fields that are unnecessary from each key and will drop keys that we do not support.

It is highly recommended to validate the output of the API call to check that the resulting keys appear as intended.

Use the `PUT` command to update keys.

Example using cURL

```

curl --request PUT \

'https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/config/{config_id}/credentials' \

--header 'Content-Type: application/json' \

--data '{

    "keys": [

        {

            "kty": "EC",

            "use": "sig",

            "kid": "test",

            "x": "-0LNzBheJPn-Zy6JmanTIUX7xc3jgqU714IQY0oU6mw",

            "y": "KONxBybUcRsJQmtu17jMAHsILSw009AuU3ulfUGv3FI",

            "alg": "ES256"

        },

        {

            "kty": "EC",

            "crv": "P-256",

            "kid": "test-2",

            "x": "iIbPRbOeLzjGPvv7iwmzCOTU03R0xDqbenp2D6GUcWo",

            "y": "tDkEh95PnfWwIXciCtdBBVA7wfghx_egmZ1Zcvu2lWw",

            "alg": "ES256"

        }

    ]

}'


```

Make sure to replace `{zone_id}` with the relevant zone ID and add your [authentication credentials](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) header.

### Update token validation rules

Token validation rules can be updated with a `PATCH` request. A single `PATCH` request can update multiple rules.

A `PATCH` request is specified as a JSON array in the request body. Each item in that array contains updates to a single rule, defined by `id`.

The following example updates one rule and disables another:

Example using cURL

```

curl --request PATCH \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/bulk"  \

--header "Content-Type: application/json" \

--data '[

    {

        "id": "714d3dd0-cc59-4911-862f-8a27e22353cc",

        "action": "log",

        "title": "updated title"

    },

    {

        "id": "7124f9bc-d6b5-430d-b488-b6bc2892f2fb",

        "enabled": false

    }

]'


```

Rules can be reordered by setting a position field in the `PATCH` body.

This example places rule `714d3dd0-cc59-4911-862f-8a27e22353cc` after rule `7124f9bc-d6b5-430d-b488-b6bc2892f2fb`:

Example using cURL

```

curl --request PATCH \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/bulk" \

--header 'Content-Type: application/json' \

--data '[

    {

        "id": "714d3dd0-cc59-4911-862f-8a27e22353cc",

        "position": {

            "after": "7124f9bc-d6b5-430d-b488-b6bc2892f2fb"

        }

    }

]'


```

This example places rule `714d3dd0-cc59-4911-862f-8a27e22353cc` before rule `7124f9bc-d6b5-430d-b488-b6bc2892f2fb`:

Example using cURL

```

curl --request PATCH \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/bulk" \

--header 'Content-Type: application/json' \

--data '[

    {

        "id": "714d3dd0-cc59-4911-862f-8a27e22353cc",

        "position": {

            "before": "7124f9bc-d6b5-430d-b488-b6bc2892f2fb"

        }

    }

]'


```

## Perform JWT validation

Here is an overview of how JWT validation processes incoming requests:

1. We extract the JWT in accordance with the configuration from the incoming request.
2. We decode the JWT and look for the JWTs header KID claim.
3. We use the KID and ALG claim to find the correct keys in the list of supplied keys.

Note

The absence of matching keys directly marks the JWT as invalid.

1. We validate the authenticity of the JWT by checking the signature using the selected key.
2. Should the JWT contain an EXP claim (expiration time), we validate that the JWT is not expired.

Note

We allow a mismatch of up to 60 seconds to account for clock drifts between the Cloudflare network and the JWT issuer. A token may still be regarded as valid one minute after it was supposed to expire when both clocks are perfectly in sync.

1. Should the JWT contain a NBF claim (not before time), we validate that the JWT is already valid.

Note

The same accuracy applies as for EXP claims. As such, a token may be already regarded as valid one minute before its NBF claim in case of perfect synchronization between issuer and validator.

1. The final validation result and whether a token was present at all is made available to the WAF which applies the policy’s configured action (`log`/`block`).
2. Security Analytics events in the Cloudflare dashboard for the `API Shield - Token Validation` service will explain violation reasons in the `Token validation violations` section of the event.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/jwt-validation/","name":"JSON Web Tokens validation"}},{"@type":"ListItem","position":5,"item":{"@id":"/api-shield/security/jwt-validation/api/","name":"Configure JWT validation via the API"}}]}
```

---

---
title: Configure the Worker
description: Use a Worker to keep your identity provider public keys updated for JWT validation.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configure the Worker

Use a Worker to automatically keep your identity provider’s latest public key in the JWT validation configuration.

## Prerequisites

* Find your zone ID. You can locate this ID in your zone overview in the [Cloudflare dashboard ↗](https://dash.cloudflare.com/).
* Find your identity provider’s JSON Web Key Set (JWKs) URL. Identity providers commonly list it in Open Authorization (OAuth) settings.
* Create a [token validation configuration](https://developers.cloudflare.com/api-shield/security/jwt-validation/#add-a-token-validation-configuration).
* [Create a new API token ↗](https://dash.cloudflare.com/profile/api-tokens) with the API Gateway `Write` permission.

## Process

You must manually query the JWKs endpoint to ensure the JWKs exists in the expected location and format. Then, create a Worker to automate updating of the JWKs and a [Worker Secret](https://developers.cloudflare.com/workers/configuration/secrets/#via-the-dashboard) to house the API key used for updating API Shield settings. You can then schedule the Worker to automatically update the JWKs.

### Manually query the JWKs endpoint

Find your Identity Provider’s URL and fetch the keys using `curl` and `jq`. Your URL may return more than just the issuer’s keys, so Cloudflare recommends using `jq` to filter the response to only return the keys. You must update the provided Worker sample code if your JWKs do not have a `keys` object.

Note

The keys listed below are for example purposes only and must not be used in your production environment, as they will never match the keys used by your identity provider to sign JWTs.

Query the JWKs endpoint

```

curl https://<your-team-name>.cloudflareaccess.com/cdn-cgi/access/certs -s | jq .keys


```

```

[

  {

    "kid": "ca96ae653935dbfb49b4e19de600cc5f9d5c63e3ac2dbee406ed4bf0ae100cce",

    "kty": "RSA",

    "alg": "RS256",

    "use": "sig",

    "e": "AQAB",

    "n": "9dG9Ph4ffncvEA9FO9pVMfJ1dh_5mtuyiIE4ap9ScrufVPq1I34St_dhcFavKiytK7Id7gTlgQgaouoJ0I5OJ_bytgX-B7oOUQHO-nJOAMycORXN8ZNaMBPKg9nBLL_BFY0YX5HggqrkXkZjJ--R4JpB30ENS8A6hxmEJ__yGMZTE2LHZoiYj9iyGNu3s3JflAoRlmziI8LsFXwyFAJUWRZq4SkSfyrRJ89pXPxIqBn9uYBtnxWzUpWG3xKZu0JAbi9YiwFCJrSe_CarvpARoWsOldtrty5yT1yJ1PZlImlF-yuEwjOoZxeib4WSidABZH0O3pbDACo8MfxR5rghHQ"

  },

  {

    "kid": "1e590a6dcd60e3e2306c21eca19144c59d591531267a3ebde8d521f40894329d",

    "kty": "RSA",

    "alg": "RS256",

    "use": "sig",

    "e": "AQAB",

    "n": "6uj6PgDq-bPsdFjiQ6M3yaxMxBUnnYj20xtLciHNafqrygAjnZKjl8LfCO_mtZ7jxfJNCARsz0L3sF9LAtARZqcsUvYLUlNDzflwNTe8woCT7yw0Ml2ZV5BWDbc3izEQnvjlBDGWv9p5jv-D-YNExtIzZKsRKyoy7hSu5FhyxmPfiAXo8b67f0dNy8V8HZfQJ5i9VGyK4Z5xKM-FjHOrC2uIbhzUE6wDe_0M23RTCxj7ZxzXUzZzc-_EBjmZDAI3tI2zBYymO55_gw8zHrNsZ4-32YvNTjBAiTLsjvKlsvNtPTN8q3saoZJWQMSiMi8dRalgA6pUDgcNs5lB9E7tWw"

  }

]


```

### Configure the Worker

1. [Create a new Worker](https://developers.cloudflare.com/workers/get-started/guide/).
2. Copy and paste the example code below into your new Worker, completely replacing any code that already exists.
3. Replace the current zone ID with your zone ID.
4. Replace the current token validation configuration ID with your token validation configuration.
5. Replace the current identity provider’s URL with your identity provider’s key URL.  
Note  
Identity provider URLs can typically be accessed at a known URL specific to your deployment. If you are unsure of the URL, contact your identity provider.
6. If your JWKs URL returns the keys in any JSON object other than `keys`, update the `fetchCredentials()` function to return only the key data.
7. Select **Create** \> **Deploy**.
8. In the Worker settings, go to **Variables** and add an environment variable named `CF_API_TOKEN` with the value of the API token that you have created.
9. In the Worker Triggers, assign a [cron trigger](https://developers.cloudflare.com/workers/configuration/cron-triggers/) to the Worker. Cloudflare recommends a frequent update interval to ensure you always have the latest keys and that an immediate key rotation by your identity provider causes minimal downtime.  
JavaScript example code  
```  
/**  
* Update Token Validation Credentials  
*  
* This example shows how a Cloudflare Workers cron trigger can be used to  
* automatically rotate a JWKs for a Token Configuration.  
*  
* To configure this Worker:  
*  
*   1. Replace `token_config_id` with the ID of the Token Config to update  
*   2. Replace `zone_id` with your Zone ID  
*   3. Replace `url` with a publicly accessible URL with the JWKs you want to use  
*   4. Create a new API Token with "Zone.API Gateway Edit" permissions and add it as a secret with the name `CF_API_TOKEN` (see https://developers.cloudflare.com/workers/configuration/secrets/)  
*  
* This worker also handles GET and POST requests:  
*   - GET will fetch and show the credentials from the provided URL (`GET https://random-worker-name-c134.example.workers.dev/`)  
*   - POST triggers an update and returns the Cloudflare API response of that update (`POST https://random-worker-name-c134.example.workers.dev/`)  
*  
* Use these to test that the Worker is properly configured.  
*  
* After setting up the worker, you can create a cron trigger to run it periodically.  
* For more information on cron triggers, refer to https://developers.cloudflare.com/workers/configuration/cron-triggers/  
*  
* Learn more about Workers at https://developers.cloudflare.com/workers/  
*/  
var zone_id = "760549bc17c54280d6e6ae256c3dd6ae";  
var token_config_id = "91007e72-8f17-46b7-a223-5e57bd333b78";  
var url = "https://cfdata.cloudflareaccess.com/cdn-cgi/access/certs"; // JWKs  
/**  
* fetchCredentials fetches new Token Configuration credentials using the URL defined above.  
* This returns a JSON string with the credentials.  
*  
* Use this function to fetch and parse credentials.  
*  
* @returns {string} credentials  
*/  
async function fetchCredentials() {  
  var requestOptions = {  
    method: "GET",  
    redirect: "follow",  
  };  
  const keys = await fetch(url, requestOptions)  
    .then((e) => e.json())  
    .then((e) => e.keys);  
  return JSON.stringify({ keys: keys });  
}  
/**  
* updateCredentials updates Token Configuration credentials using the Cloudflare API.  
* Credentials are fetched using fetchCredentials, which also does any required processing.  
*  
* @param {string} bearer Cloudflare API Bearer token with "Zone.API Gateway Edit" permissions  
* @returns {string} Cloudflare API response from the update request  
*/  
async function updateCredentials(bearer) {  
  // Cloudflare API endpoint for credentials update  
  const url = `https://api.cloudflare.com/client/v4/zones/${zone_id}/token_validation/config/${token_config_id}/credentials`;  
  const init = {  
    body: await fetchCredentials(),  
    method: "PUT",  
    headers: {  
      Authorization: `Bearer ${bearer}`,  
      "content-type": "application/json;charset=UTF-8",  
    },  
  };  
  const response = await fetch(url, init);  
  return response.text();  
}  
// Export a default object containing event handlers  
export default {  
  /**  
  * fetch handles requests made directly to the Worker.  
  *  
  */  
  async fetch(request, env, ctx) {  
    let responseBody = "";  
    if (request.method === "GET") {  
      responseBody = await fetchCredentials();  
    } else if (request.method === "POST") {  
      responseBody = await updateCredentials(env.CF_API_TOKEN);  
    }  
    return new Response(responseBody, {  
      headers: { "content-type": "application/json;charset=UTF-8" },  
    });  
  },  
  /**  
  * scheduled is the handler for cron triggers.  
  *  
  * For details, refer to https://developers.cloudflare.com/workers/configuration/cron-triggers/  
  *  
  */  
  async scheduled(request, env, ctx) {  
    ctx.waitUntil(updateCredentials(env.CF_API_TOKEN));  
  },  
};  
```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/jwt-validation/","name":"JSON Web Tokens validation"}},{"@type":"ListItem","position":5,"item":{"@id":"/api-shield/security/jwt-validation/jwt-worker/","name":"Configure the Worker"}}]}
```

---

---
title: Enhance Transform Rules
description: Forward verified JWT claims to your origin using Transform Rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Enhance Transform Rules

You can forward information from a [JSON Web Token (JWT)](https://developers.cloudflare.com/api-shield/security/jwt-validation/) to the origin in a header by creating [Transform Rules](https://developers.cloudflare.com/rules/transform/) using claims that Cloudflare has verified via the JSON Web Token.

Claims are available through the `http.request.jwt.claims` firewall fields.

For example, the following expression will extract the user claim from a token processed by the token configuration with `TOKEN_CONFIGURATION_ID`:

```

lookup_json_string(http.request.jwt.claims["<TOKEN_CONFIGURATION_ID>"][0], "claim_name")


```

Refer to [Configure JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/api/) for more information about creating a token configuration.

## Create a Transform Rule

As an example, to send the `x-send-jwt-claim-user` request header to the origin, you must create a Transform Rule:

1. In the Cloudflare dashboard, go to the **Rules overview** page.  
[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/rules/overview)
2. Select **Create rule** \> **Request Header Transform Rules**.
3. Enter a rule name and a filter expression, if applicable.
4. Choose **Set dynamic**.
5. Set the header name to `x-send-jwt-claim-user`.
6. Set the value to:  
```  
lookup_json_string(http.request.jwt.claims["<TOKEN_CONFIGURATION_ID>"][0], "claim_name")  
```  
`<TOKEN_CONFIGURATION_ID>` is your token configuration ID found in JWT validation and `claim_name` is the JWT claim you want to add to the header.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/jwt-validation/","name":"JSON Web Tokens validation"}},{"@type":"ListItem","position":5,"item":{"@id":"/api-shield/security/jwt-validation/transform-rules/","name":"Enhance Transform Rules"}}]}
```

---

---
title: Mutual TLS (mTLS)
description: Require client certificates to authenticate API requests with mutual TLS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Mutual TLS (mTLS)

Note

While API Shield is not required to use mTLS, many teams may use mTLS to protect their APIs.

[Mutual TLS (mTLS)](https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/) authentication is a common security practice that uses client certificates to ensure traffic between client and server is bidirectionally secure and trusted. mTLS also allows requests that do not authenticate via an identity provider — such as Internet-of-things (IoT) devices — to demonstrate they can reach a given resource.

Use mTLS when you need to verify the identity of API clients, such as mobile applications, IoT devices, or services that connect to your API.

![mTLS sequence diagram](https://developers.cloudflare.com/_astro/api-shield-call-sequence.DjXyNgan_CJbMD.webp) 

mTLS also supports [gRPC ↗](https://grpc.io/docs/what-is-grpc/introduction/)\-based APIs, which use binary formats such as protocol buffers rather than JSON.

## Setup

To set up mTLS for one or more hosts using the dashboard, refer to [Configure mTLS](https://developers.cloudflare.com/api-shield/security/mtls/configure/).

## Availability

All Cloudflare plans can set up mTLS with a Cloudflare-managed certificate authority (CA). Enterprise customers can [upload up to five non-Cloudflare CAs](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/). For higher limits, contact your account team.

## Limitations

When using Yubikeys, the browser may prompt for unlocking the key due to a problem in Yubikey's PKCS#11 library.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/mtls/","name":"Mutual TLS (mTLS)"}}]}
```

---

---
title: Bring your own CA for mTLS
description: Cloudflare mTLS now supports client certificates that have not been issued by Cloudflare CA. Learn how you can bring your own CA and use it with Cloudflare mTLS.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Bring your own CA for mTLS

This page explains how you can manage client certificates that have not been issued by Cloudflare CA. For a broader overview, refer to the [mTLS at Cloudflare learning path](https://developers.cloudflare.com/learning-paths/mtls/concepts/).

Bring your own CA (BYOCA) is especially useful if you already have mTLS implemented and [client certificates are already installed](https://developers.cloudflare.com/ssl/client-certificates/#how-it-works) on devices.

## Availability

* This feature is only available on Enterprise accounts.
* Each Enterprise account can upload up to five CAs. This quota does not apply to CAs uploaded through [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/mutual-tls-authentication/).
* The CA certificate quota is shared across [API Shield](https://developers.cloudflare.com/api-shield/security/mtls/configure/), [Workers mTLS](https://developers.cloudflare.com/workers/runtime-apis/bindings/mtls/), and [Cloudflare Gateway](https://developers.cloudflare.com/cloudflare-one/traffic-policies/).
* To increase this quota, contact your account team.

Note

If you exceed the CA certificate quota, the API returns error `1489` with the message "Hit maximum CA cert allocation." Contact your account team to request a quota increase.

## CA certificate requirements

When you upload your CA, Cloudflare validates the certificate according to certain requirements.

* The CA certificate can be from a publicly trusted CA or self-signed.
* In the certificate `Basic Constraints`, the attribute `CA` must be set to `TRUE`.
* The certificate must use one of the signature algorithms listed below:  
Allowed signature algorithms  
`x509.SHA1WithRSA`  
`x509.SHA256WithRSA`  
`x509.SHA384WithRSA`  
`x509.SHA512WithRSA`  
`x509.ECDSAWithSHA1`  
`x509.ECDSAWithSHA256`  
`x509.ECDSAWithSHA384`  
`x509.ECDSAWithSHA512`

Note

Uploading the CA private key is only required if you wish to use [Zero Trust's block page](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/user-side-certificates/custom-certificate/). To upload your own CA with the private key, use the [Upload mTLS certificate](https://developers.cloudflare.com/api/resources/mtls%5Fcertificates/methods/create/) endpoint.

## Set up mTLS with your CA

* [ Dashboard ](#tab-panel-10421)
* [ API ](#tab-panel-10422)

1. In the Cloudflare dashboard, go to the **Client Certificates** page.  
[ Go to **Client Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. Select **Add Certificate**.
3. In the **Certificate Authority** dropdown, select **Bring your own CA**.
4. Upload your CA certificate file (PEM encoded) and enter a name for the CA.
5. Select **Continue**.
6. On the **Associate Hostnames** page, enter the hostname that should use this CA for mTLS validation and select **Add** for each one. You can also skip this step and associate hostnames later.
7. Select **Save** to confirm.

1. Use the [Upload mTLS certificate endpoint](https://developers.cloudflare.com/api/resources/mtls%5Fcertificates/methods/create/) to upload the CA root certificate.
* `ca` boolean required  
   * Set to `true` to indicate that the certificate is a CA certificate.
* `certificates` string required  
   * Insert content from the `.pem` file associated with the CA certificate, formatted as a single string with `\n` replacing the line breaks.
* `name` string optional  
   * Indicate a unique name for your CA certificate.
* `private_key` string optional  
   * Insert content from the `.pem` file associated with the private key for the certificate, formatted as a single string with `\n` replacing the line breaks.
1. Take note of the certificate ID (`id`) that is returned in the API response.
2. Use the [Replace Hostname Associations endpoint](https://developers.cloudflare.com/api/resources/certificate%5Fauthorities/subresources/hostname%5Fassociations/methods/update/) to enable mTLS in each hostname that should use the CA for mTLS validation. Use the following parameters:
* `hostnames` array required  
   * List the hostnames that will be using the CA for client certificate validation.  
   Warning  
   Submitting an empty array will remove all hostname associations.
* `mtls_certificate_id` string required  
   * Indicate the certificate ID obtained from the previous step.  
   Warning  
   If no `mtls_certificate_id` is provided, the action will be performed against the [Cloudflare-managed CA](https://developers.cloudflare.com/ssl/client-certificates/).
1. (Optional) Make a [GET request](#list-ca-hostname-associations) to confirm the CA hostname associations.

After uploading the CA and associating hostnames, create a custom rule to enforce client certificate validation. You can do this [via the dashboard](https://developers.cloudflare.com/learning-paths/mtls/mtls-app-security/#3-validate-the-client-certificate-in-the-waf) or [via API](https://developers.cloudflare.com/waf/custom-rules/create-api/).

```

  "expression": "(http.host in {\"<HOSTNAME_1>\" \"<HOSTNAME_2>\"} and not cf.tls_client_auth.cert_verified)",

  "action": "block"


```

Note

When using [CNAME records](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#cname), enforce mTLS on the specific hostname where it should be checked. It is not enough to have it set on the CNAME target.

### Multiple CAs for one hostname

There can be multiple CAs (Cloudflare-managed or BYOCA) associated with the same hostname. For BYOCA certificates, the most recently deployed certificate will be prioritized.

If you wish to remove the association from the Cloudflare-managed certificate and only use your BYOCA certificate(s):

* [ Dashboard ](#tab-panel-10427)
* [ API ](#tab-panel-10428)

1. In the Cloudflare dashboard, go to the **Client Certificates** page.  
[ Go to **Client Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. On the **Hosts** section under **Cloudflare-issued Client Certificates**, select **Edit**.
3. Select the cross next to the hostname you want to remove.
4. Select **Save** to confirm.

1. [List the hostname associations](https://developers.cloudflare.com/api/resources/certificate%5Fauthorities/subresources/hostname%5Fassociations/methods/get/) **without** the `mtls_certificate_id` parameter.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`
* `SSL and Certificates Read`

List Hostname Associations

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/certificate_authorities/hostname_associations" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

1. Copy the `hostnames` array returned by the API and update it, removing the hostname that should no longer use the Cloudflare-managed CA.
2. Use the [Replace Hostname Associations endpoint](https://developers.cloudflare.com/api/resources/certificate%5Fauthorities/subresources/hostname%5Fassociations/methods/update/) **without** the `mtls_certificate_id` parameter to perform the action against the Cloudflare-managed CA. For `hostnames` use the list from the previous step.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`

Replace Hostname Associations

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/certificate_authorities/hostname_associations" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "hostnames": [

        "<UPDATED_HOSTNAME_ASSOCIATIONS>"

    ]

  }'


```

## Delete an uploaded CA

If you want to remove a CA that you have previously uploaded, you must first remove any hostname associations that it has.

* [ Dashboard ](#tab-panel-10423)
* [ API ](#tab-panel-10424)

1. In the Cloudflare dashboard, go to the **Client Certificates** page.  
[ Go to **Client Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. Select the **BYOCA** tab.
3. Find the CA you want to delete and select the three dots next to it.
4. Remove all associated hostnames first, if any exist.
5. Select the delete option and confirm.

1. Make a request to the [Replace Hostname Associations endpoint](https://developers.cloudflare.com/api/resources/certificate%5Fauthorities/subresources/hostname%5Fassociations/methods/update/), with an empty array for `hostnames` and specifying your CA certificate ID in `mtls_certificate_id`:

```

  "hostnames": [],

  "mtls_certificate_id": "<CERTIFICATE_ID>"


```

1. Use the [Delete mTLS certificate endpoint](https://developers.cloudflare.com/api/resources/mtls%5Fcertificates/methods/delete/) to delete the certificate.

## List CA hostname associations

* [ Dashboard ](#tab-panel-10425)
* [ API ](#tab-panel-10426)

1. In the Cloudflare dashboard, go to the **Client Certificates** page.  
[ Go to **Client Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. Select the **BYOCA** tab.
3. Find the CA you want to inspect and select the three dots next to it.
4. Select **Edit hostnames**. The **Certificate Details** panel displays the associated hostnames.

Use the [List Hostname Associations endpoint](https://developers.cloudflare.com/api/resources/certificate%5Fauthorities/subresources/hostname%5Fassociations/methods/get/) with the `mtls_certificate_id` query parameter set to the certificate ID of the uploaded CA.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`
* `SSL and Certificates Read`

List Hostname Associations

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/certificate_authorities/hostname_associations?mtls_certificate_id=ID_FROM_STEP_2" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/client-certificates/","name":"Client certificates (mTLS)"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/client-certificates/byo-ca/","name":"Bring your own CA for mTLS"}}]}
```

---

---
title: Configure mTLS
description: Set up mTLS authentication rules to require client certificates for API hosts.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configure mTLS

When you specify API hosts in [mTLS authentication](https://developers.cloudflare.com/api-shield/security/mtls/), Cloudflare will block all requests that do not have a [client certificate](https://developers.cloudflare.com/ssl/client-certificates/) for mTLS authentication.

## Prerequisites

Before you can protect your API or web application with mTLS rules, you need to:

* Check that the certificate installed on your origin server matches the hostname of the client certificate, for example `api.example.com`. Origin server wildcard certificates such as `*.example.com` are not supported.
* [Create a client certificate](https://developers.cloudflare.com/ssl/client-certificates/create-a-client-certificate/).
* [Configure your mobile app or IoT device](https://developers.cloudflare.com/ssl/client-certificates/configure-your-mobile-app-or-iot-device/) to use your Cloudflare-issued client certificate.
* [Enable mutual Transport Layer Security (mTLS) for a host](https://developers.cloudflare.com/ssl/client-certificates/enable-mtls/) in your zone.

Note

While API Shield is not required to use mTLS, many teams may use mTLS to protect their APIs.

Warning

By default, API Shield mTLS uses client certificates issued by a Cloudflare-managed CA. If you need to use certificates issued by another CA, refer to [Bring your own CA for mTLS](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/).

## Create an mTLS rule via the Cloudflare dashboard

1. In the Cloudflare dashboard, go to **Client Certificates** page.  
[ Go to **Client Certificates** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. Select **Create a mTLS rule**.
3. In **Custom rules**, several rule parameters have already been filled in. Enter the URI path you want to protect in **Value**.
4. (Optional) Add a `Hostname` field and enter the mTLS-enabled hostnames you wish to protect in **Value**.
5. In **Choose action**, select `Block`.
6. Select **Deploy** to make the rule active.

Once you have deployed your mTLS rule, any requests without a [valid client certificate](https://developers.cloudflare.com/ssl/client-certificates/) will be blocked.

### Expression Builder

To review your mTLS rule in the Expression Builder, select the **wrench icon** associated with your rule.

In the **Expression Preview**, your mTLS rule includes a [compound expression](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/#compound-expressions) formed from two [simple expressions](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/#simple-expressions) joined by the `and` operator.

The first expression — `not cf.tls_client_auth.cert_verified` — returns `true` when a request to access your API or web application does not present a valid client certificate.

The second expression uses the `http.request.uri.path` field, combined with the `in` operator, to capture the URI paths your mTLS rule applies to.

Because the [action](https://developers.cloudflare.com/ruleset-engine/rules-language/actions/) for your rule is _Block_, only requests that present a valid client certificate can access the specified hosts.

Cloudflare recommends also validating the issuer Subject Key Identifier (SKI) hash. Without this check, any valid client certificate is accepted regardless of which certificate authority (CA) issued it. Adding the SKI hash restricts access to certificates from a specific CA.

You can implement this by using an expression similar to the following:

```

not (cf.tls_client_auth.cert_verified and cf.tls_client_auth.cert_issuer_ski eq "A5AC554235DBA6D963B9CDE0185CFAD6E3F55E9F")


```

To obtain the issuer Subject Key Identifier (SKI) hash of a client certificate stored in the `mtls.crt` file, you can run the following OpenSSL command:

Terminal window

```

openssl x509 -noout -ext authorityKeyIdentifier -in mtls.crt | tail -n1 | tr -d ': '


```

```

A5AC554235DBA6D963B9CDE0185CFAD6E3F55E9F


```

### Check for revoked certificates

To check for [revoked client certificates](https://developers.cloudflare.com/ssl/client-certificates/revoke-client-certificate/), you can either add a new mTLS rule or add a new expression to the [default rule](#expression-builder). To check for revoked certificates, you must use the Expression Builder.

When a request includes a revoked certificate, the `cf.tls_client_auth.cert_revoked` field is set to `true`. If you combined this with the [default mTLS rule](#expression-builder), it would look similar to the following:

```

((not cf.tls_client_auth.cert_verified or cf.tls_client_auth.cert_revoked) and http.request.uri.path in {"/admin"})


```

Warning

This check only applies to client certificates issued by the Cloudflare-managed CA. Cloudflare currently does not check certificate revocation lists (CRL) for [CAs that have been uploaded](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/mtls/","name":"Mutual TLS (mTLS)"}},{"@type":"ListItem","position":5,"item":{"@id":"/api-shield/security/mtls/configure/","name":"Configure mTLS"}}]}
```

---

---
title: Schema validation
description: Validate API requests against OpenAPI schemas to block malformed or unexpected traffic.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Schema validation

 Available on all plans 

The API schema defines which API requests are valid based on several request properties like target endpoint, path or query variable format, and HTTP method.

Schema validation allows you to check if incoming traffic complies with a previously supplied API schema. When you provide an API schema or select from a list of learned schema, API Shield creates rules for incoming traffic from the schema definitions. These rules define which traffic is allowed and which traffic gets logged or blocked.

Schema validation 2.0 is the current version. For help configuring the previous version for one or more hosts using the dashboard, refer to [Configure Classic Schema validation](https://developers.cloudflare.com/api-shield/reference/classic-schema-validation/). You can make changes to your Classic Schema validation settings but you cannot add any new schemas.

You can migrate to Schema validation 2.0 manually by uploading your schemas to the new system.

---

## Process

Endpoints must be added to [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/) for Schema validation to protect them. Uploading a schema via the Cloudflare dashboard will automatically add endpoints, or you can manually add them from [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/).

If you are uploading a schema via the API or Terraform, you must parse the schema and add your endpoints manually.

The API endpoint is the location where API calls or requests are fulfilled. API Shield defines endpoints as a host, method, and path tuple.

Note

To view the contents in your learned schema, refer to [Export a schema](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/#export-a-schema) in Endpoint Management.

---

### Add validation by uploading a schema

* [  New dashboard ](#tab-panel-6567)
* [ Old dashboard ](#tab-panel-6568)

1. In the Cloudflare dashboard, go to the **Web Assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Schema validation** tab.
3. Select **Add validation**.
4. Upload a schema file.
5. Select **Add schema and endpoints**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Select **Security** \> **API Shield**.
3. Go to **Schema validation** and select **Add validation**.
4. Select your schema file for upload.
5. Observe the listed endpoints, their host, method, and path. Any new endpoints will automatically be added to Endpoint Management.
6. Choose an action for the non-compliant requests to your endpoints.
7. Select **Add schema and endpoints**.

Note

Changes may take a few minutes to process depending on the number of added endpoints.

### Add validation by applying a learned schema to a single endpoint

* [  New dashboard ](#tab-panel-6569)
* [ Old dashboard ](#tab-panel-6570)

1. In the Cloudflare dashboard, go to the **Web Assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Schema validation** tab.
3. Select **Add validation**.
4. Select **Apply learned schema**.
5. Choose an action and select **Apply schema**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Select **Security** \> **API Shield**.
3. Go to **Schema validation** and filter by the learned schema available.
4. Select **Apply learned schema**.
5. Choose an action and select **Apply schema**.

### Add validation by applying a learned schema to an entire hostname

At this time, learned schemas will not overwrite customer-uploaded schemas. If an endpoint is covered by a customer-uploaded schema and also appears in a learned schema, the **Changes** field is set to `Unaffected`.

* [  New dashboard ](#tab-panel-6571)
* [ Old dashboard ](#tab-panel-6572)

1. In the Cloudflare dashboard, go to the **Web Assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Schema validation** tab.
3. Select **Add validation**.
4. Select **Apply learned schema**.
5. Choose a hostname and review the endpoints that will be protected by the learned schema.
6. (Optional) Change the action if a request does not match the schema.
7. Select **Apply schema**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Select **Security** \> **API Shield**.
3. Go to **Schema validation** and select **Add validation**.
4. Select **Apply learned schema**.
5. Choose a hostname and review the endpoints that will be protected by the learned schema.
6. (Optional) Change the action if a request does not match the schema.
7. Select **Apply schema**.

Note

If an endpoint is currently protected by a learned schema, the date of the last applied learned schema will be shown in the current schema field.

### Add validation by adding a fallthrough rule

A fallthrough rule acts as a catch-all for requests that do not match endpoints in [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/).

By ensuring that all your endpoints in a schema are added to Endpoint Management, the fallthrough action can protect you against legacy or zombie endpoints that your team may be unaware of.

To set up a fallthrough action:

* [  New dashboard ](#tab-panel-6585)
* [ Old dashboard ](#tab-panel-6586)

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. Select **Templates**.
3. Search for the template named `Mitigate API requests to unidentified endpoints` and select **Preview template**.
4. Give your rule a descriptive name.
5. Choose one or more hostnames from the dropdown menu and select your action.
6. Select **Save as draft** to deploy later, or **Deploy** to deploy now.

Your current fallthrough rules can be viewed in the security rules list.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **API Shield**.
3. Under **Settings**, go to **Fallthrough settings**.
4. Select **Use Template**.
5. Choose one or more hostnames from the drop down menu. The fallthrough rule will act on all traffic that does not match an existing endpoint in Endpoint Management to the selected hostnames.
6. Select **Continue to custom rule**.
7. Name your rule and select your action.
8. Select **Save as draft** to deploy later, or **Deploy** to deploy now.

Your current fallthrough rules can be viewed in the custom rules list.

Note

You can use the `cf.api_gateway.fallthrough_detected` field in your own custom rule for a more customized logic check. This field evaluates as `true` when a request does not match an endpoint in Endpoint Management. Check against your API hostname or root path to ensure that you are not blocking non-API traffic on your zone.

### Change the action of an entire schema

* [  New dashboard ](#tab-panel-6573)
* [ Old dashboard ](#tab-panel-6574)

1. In the Cloudflare dashboard, go to the **Web Assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Schema validation** tab.
3. Check the multi-select box to select all endpoints associated with the schema.
4. Select **Change action**.
5. Choose an action from the dropdown menu.
6. Select **Set action**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Select **Security** \> **API Shield**.
3. Go to **Schema validation** and select the schema in the Schema list.
4. Check the multi-select box to select the endpoints shown on the current page.
5. Choose **Select all endpoints**.
6. Select **Change action**.
7. Choose an action from the dropdown menu.
8. Select **Set action**.

### Change the global default action of Schema validation

Schema validation’s default action is visible on the main Schema validation page. This action applies to any endpoint with its action set to `Default`.

* `Log` action: logs events to [Firewall Events](https://developers.cloudflare.com/firewall/).
* `Block` action: blocks requests that fail the schema for an endpoint and logs events to [Firewall Events](https://developers.cloudflare.com/firewall/).
* `None` action: non-compliant requests are neither logged nor blocked.

To change the default action:

* [  New dashboard ](#tab-panel-6575)
* [ Old dashboard ](#tab-panel-6576)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **API abuse**.
3. Under **Schema validation** \> **Configurations**, select the edit icon next to **Default action**.
4. Choose a new action from the dropdown menu.
5. Select **Save**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **API Shield**.
3. Select **Schema validation**.
4. Under the default `Log` action, select **Change**.
5. Choose a new action from the dropdown menu.
6. Observe the current action and accept the change by selecting **Change default action** in the popup window.

Alternatively, you can modify the global action via **Security** \> **API Shield** \> **Settings**.

### Change the action of a single endpoint

You can change individual endpoint actions separately from the default action in Schema validation.

This allows you to be stricter on blocking non-compliant requests on certain endpoints when the default action is `Log`. It can also be used to relax constraints on non-compliant requests on certain endpoints when the default action is set to `Block`. You may want to silence known false positives on an endpoint by setting the action to `None`.

To change the action on an individual endpoint:

* [  New dashboard ](#tab-panel-6577)
* [ Old dashboard ](#tab-panel-6578)

1. In the Cloudflare dashboard, go to the **Web Assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Schema validation** tab.
3. Search for the endpoint to change.
4. Select the three dots on the endpoint's row > **Change action**.
5. Choose a new action from the dropdown menu and select **Set action**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **API Shield**.
3. Select **Schema validation** and filter the selected endpoint.
4. Select the ellipses on the endpoint's row.
5. Select **Change action**.
6. Choose a new action from the dropdown menu and select **Set action**.

### Disable Schema validation without changing actions

You can disable Schema validation entirely for temporary troubleshooting. You can override all actions at once, preventing Schema validation from taking any action while you complete your troubleshooting.

To disable Schema validation without changing actions:

* [  New dashboard ](#tab-panel-6579)
* [ Old dashboard ](#tab-panel-6580)

1. In the Cloudflare dashboard, go to the **Web Assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Schema validation** tab.
3. Select **Schema settings**.
4. Filter by **API abuse**.
5. Turn **Schema validation** off.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Select **Security** \> **API Shield**.
3. Go to the **Schema validation** settings.
4. Select **Disable**.

Your per-endpoint configurations will be saved when modifying the setting, so that you do not lose your configuration. To re-enable your configurations after troubleshooting, navigate back to the settings and select **Enable**.

### View active schemas

* [  New dashboard ](#tab-panel-6581)
* [ Old dashboard ](#tab-panel-6582)

1. In the Cloudflare dashboard, go to the **Web Assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Schema validation** tab.
3. Select **Schema settings**.
4. Filter by **API abuse**.
5. View your schemas on **Schema validation** \> **Active schemas**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Select **Security** \> **API Shield**.
3. Go to your **Schema validation** settings.
4. View your schemas under **Uploaded Schemas** and **Learned schemas**.
5. Select **Filter** on the endpoints in either schema.

Note

To export a schema, refer to [Export a schema](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/#export-a-schema).

### Delete active schemas

Deleting the schema will remove validation from the currently associated endpoints, but it will not delete the endpoints from Endpoint Management.

To delete currently uploaded or learned schemas:

* [  New dashboard ](#tab-panel-6583)
* [ Old dashboard ](#tab-panel-6584)

1. In the Cloudflare dashboard, go to the **Web Assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Schema validation** tab.
3. Select **Schema settings**.
4. Filter by **API abuse**.
5. View your schemas on **Schema validation** \> **Active schemas**.
6. Select the ellipses to access the menu and download or delete the listed schema.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Select **Security** \> **API Shield**.
3. Go to your **Schema validation** settings.
4. View your schemas under **Uploaded Schemas** and **Learned schemas**.
5. Select the ellipses to access the menu and download or delete the listed schema.

---

## Specifications

Cloudflare currently only accepts [OpenAPI v3 schemas ↗](https://spec.openapis.org/oas/v3.0.3.html). The accepted file formats are YAML (`.yml` or `.yaml` file extension) and JSON (`.json` file extension).

OpenAPI schemas generated by different tooling may not be specific enough to import to Schema validation. Use a third-party tool such as [Swagger Editor ↗](https://swagger.io/tools/swagger-editor/) to ensure that schemas are compliant to the OpenAPI specification.

---

## Limitations

Cloudflare API Shield's Schema validation (importing) and [Schema learning](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/) (exporting) capabilities rely on the [OpenAPI Specification (OAS) v3.0 ↗](https://spec.openapis.org/oas/v3.0.3).

This support includes all patch versions, such as OAS v3.0.x. OAS v3.1 is not supported, and there are no plans to expand support for OpenAPI 2.0.

Note

Cloudflare recommends using a third-party tool like [Swagger Editor ↗](https://editor.swagger.io/) to ensure that all schemas are fully compliant with the OAS v3.0 specification before upload.

Currently, API Shield does not support some features of API schemas, including the following: all responses, external references, non-basic path templating, or unique items.

There is a limit of 10,000 total operations for enabled schemas for Enterprise customers subscribed to [API Shield](https://developers.cloudflare.com/api-shield/). To raise this limit, contact your account team.

### Body size for validation

Schema validation inspects request bodies up to a maximum size that depends on your zone plan. Request bodies that exceed this limit are not validated against your schema, and the configured [Schema validation action](https://developers.cloudflare.com/api-shield/security/schema-validation/#change-the-global-default-action-of-schema-validation) will not apply to those requests.

The default body size limits are:

| Plan       | Default body size limit |
| ---------- | ----------------------- |
| Free       | 1 KB                    |
| Pro        | 8 KB                    |
| Business   | 8 KB                    |
| Enterprise | 128 KB                  |

Note

This limit is separate from the [WAF maximum body inspection size](https://developers.cloudflare.com/waf/managed-rules/#maximum-body-size), which controls how much of the request payload the WAF scans. Increasing one does not affect the other.

#### Identify requests exceeding the body size limit

If Schema validation is blocking or logging requests due to the body size limit, you will see events in **Security** \> **Events** with the Schema validation rule as the source.

For limits on Free, Pro, Business, or Enterprise customers not subscribed to API Shield, refer to [Plans](https://developers.cloudflare.com/api-shield/plans/).

### Required fields

Although not strictly required by the OpenAPI specification, Schema validation strictly requires these fields.

#### `schema`

* [type ↗](https://spec.openapis.org/oas/v3.0.3#schema-object)  
   * All schemas require a type to be set. If the specific type is not supported by Schema validation, set the type to `string` instead.

#### `parameter`

* [schema ↗](https://spec.openapis.org/oas/v3.0.3#schema-object)  
   * Schema validation does not support the content field in parameters. For more details, refer to the [notes on validated and supported fields](#notes-on-validated-and-supported-fields) below. Instead, a schema is strictly required on all parameters objects.

### Notes on validated and supported fields

Refer to the information below for more details on Schema validation's current support for various OpenAPI specification (OAS) objects and fields.

#### `servers`

* [url ↗](https://spec.openapis.org/oas/v3.0.3#server-object)  
   * Schema validation does not support relative URLs.
* [variables ↗](https://spec.openapis.org/oas/v3.0.3#server-variable-object)  
   * Server variables are not validated.

#### `parameter`

* [style ↗](https://spec.openapis.org/oas/v3.0.3#parameter-object)  
   * Only the default values are supported: `"simple"` (path or header parameters) and `"form"` (query or cookie parameters).
* [explode ↗](https://spec.openapis.org/oas/v3.0.3#parameter-object)  
   * Only the default values are supported: `true` (for form) and `false` (for simple).
* [content ↗](https://spec.openapis.org/oas/v3.0.3#parameter-object)  
   * The content field is not supported in parameters. Use the schema field instead.
* [type ↗](https://spec.openapis.org/oas/v3.0.3#parameter-object)  
   * Cloudflare currently does not validate object type parameters.

#### `reference`

* [$ref ↗](https://spec.openapis.org/oas/v3.0.3#reference-object)  
   * External or relative references are not supported.

#### `requestBody`

* `content`  
   * [Request Body Object ↗](https://spec.openapis.org/oas/v3.0.3#request-body-object)  
   * [Media Type Object ↗](https://spec.openapis.org/oas/v3.0.3#media-type-object)  
         * Schema validation is able to validate `application/json` documents. If a given schema allows other content types, Schema validation will accept those requests without validation.

#### `parameter/schema`

* `anyOf`  
   * [Parameter Object ↗](https://spec.openapis.org/oas/v3.0.3#parameter-object)  
   * [Schema Object ↗](https://spec.openapis.org/oas/v3.0.3#schema-object)  
         * `anyOf` schemas are currently not supported in parameter schemas.

#### `schema`

* [format ↗](https://spec.openapis.org/oas/v3.0.3#schema-object)  
   * Validated formats:  
         * `date-time`  
         * `time`  
         * `date`  
         * `email`  
         * `hostname`  
         * `ipv4`  
         * `ipv6`  
         * `uri`  
         * `uri-reference`  
         * `iri`  
         * `iri-reference`  
         * `int32`  
         * `int64`  
         * `float`  
         * `double`  
         * `password`  
         * `uuid`  
         * `byte`  
         * `uint64`
* [uniqueItems ↗](https://spec.openapis.org/oas/v3.0.3#schema-object)  
   * This field is currently not validated by Schema validation.

---

## Body inspection

API Shield has the ability to identify body specifications contained in uploaded schemas and validate that the data of incoming API requests adheres to them.

Schema validation currently supports validating requests with content-type `application/json`.

Within the OpenAPI specification, request body schemas are associated to media-ranges (such as `application/*`, `application/xml` or `application/json`).

When Cloudflare validates incoming requests, Cloudflare checks that the request's `content-type` matches the OpenAPI-specified media-range.

For example, when the OpenAPI file specifies `application/*` as part of the request body content map, Cloudflare will accept requests with the content-types `application/xml` and `application/json`. However, only `application/json` bodies will be validated with the supplied schema.

Cloudflare recommends keeping the media-ranges as tight as possible by setting them to an individual media-type. If you need to support multiple content-types on an API endpoint, you can utilize wildcard media-ranges.

Care should also be taken if the origin is configured to perform [MIME sniffing ↗](https://mimesniff.spec.whatwg.org/). For example, when a request carrying a JSON body is deliberately carrying an `application/malicious` content-type and Cloudflare was configured to allow `application/*` media-ranges, the request would be passed along to the origin without validating the JSON body contents. However, an origin that ignores the content-type and either trial deserializes or sniffs the MIME type may deserialize the JSON body with a wrong assumption of having passed schema body validation.

As such, if you need to support `application/json` and `application/xml` on the same endpoint, you can use `application/*`. Cloudflare will validate the provided schema for request bodies where the content-type is set to `application/json`. Requests with content-type `application/xml` (and others matching `application/*`) will be let through. It is still strongly advised to disable content-type sniffing on your origin.

Cloudflare allows specifying the following media-ranges in the OpenAPI request body content map:

* `*/*`
* `application/*`
* `application/json`.

Media-ranges can also be configured to enforce a `charset` parameter. For this, Cloudflare only accepts the `charset` parameter with a static value of `utf-8` as part of the media-range specification and when configured, we will similarly require the request's content-type to carry this charset.

---

## Troubleshooting

This section addresses common issues you may encounter when using schema validation.

### `OneOf` constraint error schema violation in the Security Events

A `OneOf` constraint error means an API request failed schema validation because its body did not match exactly one of the options defined in a [oneOf ↗](https://swagger.io/docs/specification/v3%5F0/data-models/oneof-anyof-allof-not/) list within your uploaded schema.

The request was invalid for one of two reasons:

* **Matches Zero**: The payload did not correctly match any of the available subschemas. This is common when a discriminator field is set, but the payload is missing other required fields for that type.
* **Matches Multiple**: The payload was ambiguous and matched more than one subschema. This happens with generic schemas (for example, if a payload includes both an `email` and a `phone` field, it might match both an `email` and a `phone` schema definition, violating the "exactly one" rule).

To fix this, check the failing request body against the API schema definition. It will either be missing required fields for the intended type or include properties from multiple different, conflicting types that make it ambiguous.

---

## Availability

Schema validation is available for all customers. Refer to [Plans](https://developers.cloudflare.com/api-shield/plans/) for more information based on your plan type.

[Schema learning](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/) is only available for customers subscribed to API Shield.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/schema-validation/","name":"Schema validation"}}]}
```

---

---
title: Configure Schema validation via the API
description: Configure per-endpoint schema validation and mitigation actions using the API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configure Schema validation via the API

Schema validation 2.0 allows all corresponding configuration calls to be made via API. This validation centers more around individual endpoints and lets you set mitigation actions for each endpoint individually. Additionally, you can use Cloudflare-provided learned schemas that we [learn automatically](https://developers.cloudflare.com/api-shield/management-and-monitoring/#endpoint-schema-learning) from your traffic for individual endpoints.

Note

[Classic Schema validation documentation](https://developers.cloudflare.com/api-shield/reference/classic-schema-validation/) is available for reference only.

## Upload schemas via the API to Schema validation

1. Upload a schema.
2. Ensure that your endpoints are added in Endpoint Management.
3. Set the schema to `active` if it is not already done.
4. Set the Schema validation zone-wide action from `none` to `log`.
5. Send test traffic that violates the schema.
6. View test traffic in Security Events by filtering for **Service** \> **API Shield - Schema validation**.
7. Optional:  
   * Set a single endpoint to `block`.  
   * Set the Schema validation zone-wide to `block`.  
   * Temporarily override all schemas zone-wide to `none`.  
   * Remove the temporary override.

Cloudflare recommends you to rerun test traffic and monitor the HTTP response codes after changing any settings to ensure Schema validation is operating as expected.

Settings changes may take a few minutes to implement.

Note

Endpoints must be listed in Endpoint Management for Schema validation to match requests.

## Configuration

### Upload and activate a schema

Upload a schema via the v4 API using `POST`. This example requires a `example_schema.yaml` schema file in the current folder.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Account API Gateway`
* `Domain API Gateway`

Upload a schema

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/schema_validation/schemas" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "kind": "openapi_v3",

    "name": "example_schema",

    "source": "<SOURCE>",

    "validation_enabled": true

  }'


```

```

{

    "result":

    {

        "schema":

        {

            "schema_id": "af632e95-c986-4738-a67d-2ac09995017a",

            "name": "example_schema",

            "kind": "openapi_v3",

            "source": "<SOURCE>",

            "created_at": "2023-04-03T15:10:08.902309Z"

        }

    },

    "success": true,

    "errors":

    [],

    "messages":

    []

}


```

By default, Schema validation is disabled for an uploaded schema so that you can inspect it first. You can upload a schema and enable it immediately by setting the form parameter `validation_enabled=true`.

Use a `PATCH` request to activate a schema after inspection.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Account API Gateway`
* `Domain API Gateway`

Enable validation for a schema

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/api_gateway/user_schemas/$SCHEMA_ID" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "validation_enabled": true

  }'


```

```

{

    "result":

    {

        "schema_id": "0bf58160-5da3-48ac-80a9-069f9642c1a0",

        "name": "api_schema.json",

        "kind": "openapi_v3",

        "validation_enabled": true,

        "created_at": "0001-01-01T00:00:00Z"

    },

    "success": true,

    "errors":

    [],

    "messages":

    []

}


```

When a schema is active, it executes the mitigation action specified for each operation. Refer to [change the default and operation-specific mitigation action](#change-the-default-and-operation-specific-mitigation-action).

### Add new operations to Endpoint Management

Schemas contain a set of servers, paths, and methods, which together define an operation. Schema validation only acts on the requests to operations which have been added to the API Shield Endpoint Management. If a schema contains operations which have not been added to Endpoint Management, they can be retrieved together with the configuration information about added operations.

cURL command

```

curl --request GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/user_schemas/{schema_id}/operations?feature=schema_info&operation_status=new&page=1&per_page=5000" \

--header "Authorization: Bearer <API_TOKEN>" \

--header 'Content-Type: application/json'


```

```

{

    "result":

        [

          {

              "method": "GET",

              "host": "example.com",

              "endpoint": "/pets"

          }

     ],

    "success": true,

    "errors": [],

    "messages": [],

    "result_info": {

        "page": 1,

        "per_page": 30,

        "count": 1,

        "total_count": 1

    }

}


```

To receive information about the configuration of existing operations, Cloudflare recommends passing the `?feature=schema_info` parameter.

You can add new operations in a schema to Endpoint Management using `POST`.

cURL command

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/operations" \

--header "Authorization: Bearer <API_TOKEN>" \

--header 'Content-Type: application/json' \

--data '[

  {

   "method": "GET",

   "host": "example.com",

   "endpoint": "/pets",

  }

]'


```

```

{

    "result":  [

            {

                "operation_id": "6c734fcd-455d-4040-9eaa-dbb3830526ae",

                "method": "GET",

                "host": "example.com",

                "endpoint": "/pets",

                "last_updated": "2023-04-04T16:07:37.575971Z"

         }

     ],

    "success": true,

    "errors":

    [],

    "messages":

    []

}


```

You can add all operations in a schema that do not already exist in Endpoint Management by combining two commands as one. There is a maximum of 20 operations for this API call. The example requires the `jq` tool.

cURL command

```

curl --silent "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/operations" \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data "$(curl --silent "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/user_schemas/{schema_id}/operations?feature=schema_info&page=1&per_page=5000" --header "Authorization: Bearer <API_TOKEN>" | jq ".result")"


```

Note

If you run this command again immediately, it will result in an error as all `new_operations` are now `existing_operations`.

### Change the default and operation-specific mitigation action

If a schema is uploaded and active for a set of operations, it validates incoming requests to each operation and decides whether a mitigation action should be taken. This mitigation action is defined per operation and can take the values **none**, **log**, and **block**, which correspond to no action, logging the requests, or blocking them before they reach the origin.

New operations will not have a mitigation action set and will use the zone-wide default mitigation action. The current default mitigation action can be retrieved using `GET`.

cURL command

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/settings/schema_validation" \

--header "Authorization: Bearer <API_TOKEN>"


```

```

{

    "result":  {

        "validation_default_mitigation_action": "none",

        "validation_override_mitigation_action": null

    }

    "success": true,

    "errors":

    [],

    "messages":

    []

}


```

A new value out of `none`, `log`, and `block` can be set using `PUT`.

cURL command

```

curl --request PUT "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/settings/schema_validation" \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "validation_default_mitigation_action": "block"

}'


```

```

{

    "result":  {

        "validation_default_mitigation_action": "block",

        "validation_override_mitigation_action": null

    }

    "success": true,

    "errors":

    [],

    "messages":

    []

}


```

If the mitigation action for an individual operation is of interest, the current value can be retrieved with `GET` using the operation ID.

cURL command

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/operations/{operation_id}/schema_validation" \

--header "Authorization: Bearer <API_TOKEN>"


```

```

{

    "result":  {

        "mitigation_action": "null"

    }

    "success": true,

    "errors":

    [],

    "messages":

    []

}


```

If the value is `null`, it means that no mitigation action has been specified for this operation and the default mitigation action is being used.

You can set the mitigation action to a value out of `none`, `block`, `log`, and `null` by using `PUT`.

cURL command

```

curl --request PUT "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/operations/{operation_id}/schema_validation" \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

    "mitigation_action": "block"

}'


```

```

{

    "result":  {

        "mitigation_action": "block"

    }

    "success": true,

    "errors":

    [],

    "messages":

    []

}


```

### List all schemas

You can get an overview of the schemas currently active on a zone using `GET`.

`validation_enabled=true` is an optional parameter.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Account API Gateway`
* `Account API Gateway Read`
* `Domain API Gateway`
* `Domain API Gateway Read`

List all uploaded schemas

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/schema_validation/schemas" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

```

{

    "result":  [

        {

          "schema_id": "af632e95-c986-4738-a67d-2ac09995017a",

          "name": "example_schema",

          "kind": "openapi_v3",

          "source": "<SOURCE>",

          "created_at": "2023-04-03T15:10:08.902309Z"

      }

    ]

    "success": true,

    "errors":

    [],

    "messages":

    []

}


```

Note

We recommend using the query parameter `omit_source=true` to only display active schemas and not retrieve the source for every schema to get less output.

### Delete a schema

You can delete a schema using `DELETE`.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Account API Gateway`
* `Domain API Gateway`

Delete a schema

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/schema_validation/schemas/$SCHEMA_ID" \

  --request DELETE \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

```

{

    "result":  null,

    "success": true,

    "errors":

    [],

    "messages":

    []

}


```

### Activate a learned schema for an operation

Cloudflare provides automatically learned parameter schemas for all operations in Endpoint Management with a sufficient amount of requests. A learned schema can be inspected using `GET`.

cURL command

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/operations/{operation_id}?feature=parameter_schemas" \

--header "Authorization: Bearer <API_TOKEN>"


```

```

{

    "result":

    {

        "operation_id": "5c734fcd-455d-4040-9eaa-dbb3830526ae",

        "method": "PATCH",

        "host": "example.com",

        "endpoint": "/pets",

        "last_updated": "2023-04-04T16:07:37.575971Z",

        "features":

        {

            "parameter_schemas":

            {

                "last_updated": "2023-04-03T20:11:55.879006Z",

                "parameter_schemas":

                {

                    "responses": null,

                    "parameters":

                    [

                        {

                            "in": "query",

                            "name": "var1",

                            "schema":

                            {

                                "type": "string"

                            },

                            "required": true,

                            "description": "Sufficient requests have been observed for this parameter to provide high confidence in this parameter schema."

                        }

                    ],

                    "x-cf-parameter-schemas": "operation schema with automatically learned path and query parameters"

                }

            }

        }

    },

    "success": true,

    "errors":

    [],

    "messages":

    []

}


```

If you are satisfied with the inspected parameter schema, you can add and activate it using `PUT`.

cURL command

```

curl --request PUT "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/operations/{operation_id}/cloudflare_learned_schema?timestamp=2023-04-03T20:11:55.879006Z" \

--header "Authorization: Bearer <API_TOKEN>"


```

```

{

    "result": null,

    "success": true,

    "errors":

    [],

    "messages":

    []

}


```

Note

Parameter schemas are updated between every 24 hours up to one week. To ensure that a parameter schema has not been updated during the inspection, Cloudflare recommends that you pass the `last_updated` timestamp of the parameter-schema feature (not the `last_updated` of the whole operation) as an identifier in the timestamp query parameter.

### Disable Schema validation

To quickly disable Schema validation for a whole zone, use `PATCH`. This operation will override all operation-mitigation actions.

cURL command

```

curl --request PATCH "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/settings/schema_validation" \

--header "Authorization: Bearer <API_TOKEN>" \

--header 'Content-Type: application/json' \

--data '{

  "validation_override_mitigation_action": "none"

}'


```

```

{

    "result":  {

        "validation_default_mitigation_action": "block",

        "validation_override_mitigation_action": "none"

    }

    "success": true,

    "errors":

    [],

    "messages":

    []

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/schema-validation/","name":"Schema validation"}},{"@type":"ListItem","position":5,"item":{"@id":"/api-shield/security/schema-validation/api/","name":"Configure Schema validation via the API"}}]}
```

---

---
title: Sequence Analytics
description: Track the order of API requests over time to discover user journeys and sequences.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Sequence Analytics

Sequence Analytics tracks the order of API endpoint requests over time, allowing you to discover how users interact with your API. Sequence Analytics groups and highlights important user journeys (sequences) across your API. You can enforce preferred sequences using [Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/).

## Process

### Sequence building

A sequence is a time-ordered list of HTTP API requests made by a specific visitor as they browse a website, use a mobile app, or interact with a B2B partner via API.

For example, a portion of a sequence made during a bank funds transfer could look like:

| Order | Method | Path                                   | Description                                                                                                                                    |
| ----- | ------ | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| 1     | GET    | /api/v1/users/{user\_id}/accounts      | user\_id is the active user.                                                                                                                   |
| 2     | GET    | /api/v1/accounts/{account\_id}/balance | account\_id is one of the user’s accounts.                                                                                                     |
| 3     | GET    | /api/v1/accounts/{account\_id}/balance | account\_id is a different account belonging to the user.                                                                                      |
| 4     | POST   | /api/v1/transferFunds                  | This contains a request body detailing an account to transfer funds from, an account to transfer funds to, and an amount of money to transfer. |

API Shield uses your configured session identifier and your saved endpoints to build a set of ordered API operations (HTTP host, method, and path) requested per session. API Shield may surface sequences in various lengths depending on how it scores the sequences.

### Sequence scoring

API Shield scores sequences by a metric called precedence score. Sequence Analytics displays sequences by the highest precedence score. High-scoring sequences contain API requests which are likely to occur together in order.

Using the example above, a high score means that the last operation in the sequence `POST /api/v1/transferFunds` is highly likely to be preceded by the other operations in sequence `GET /api/v1/users/{user_id}/accounts` followed by `GET /api/v1/accounts/{account_id}/balance`. The scores are probabilities, which API Shield estimates using data from the last 24 hours.

### Secure your API

To proactively secure your API, you should inspect your highest-scoring sequences. For each high-scoring sequence, you should confirm with your development team if the final operation in the sequence must legitimately always be preceded by the other operations in the sequence.

Using the above example, if `POST /api/v1/transferFunds` must legitimately always be preceded by `GET /api/v1/users/{user_id}/accounts` and `GET /api/v1/accounts/{account_id}/balance`, you should create an **Allow** rule in sequence mitigation on the final operation of the sequence.

You should also consider applying other API Shield protections to these endpoints ([rate limiting suggestions](https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/), [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/), and [mTLS](https://developers.cloudflare.com/api-shield/security/mtls/)).

For more information, refer to the [blog post ↗](https://blog.cloudflare.com/api-sequence-analytics).

### Repeated sequences

Real-world API usage shows many successively repeated operations. To facilitate exploration, Sequence Analytics collapses successively repeated operations into one.

## Availability

Sequence Analytics is available for all API Shield customers. Pro, Business, and Enterprise customers who have not purchased API Shield can get started by [enabling the API Shield trial ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/api-shield) in the Cloudflare dashboard or contacting your account manager.

## Limitations

Sequence Analytics currently requires a session identifier and saved endpoints in order to build and track sequences made by an API consumer. Ensure that you have [set up your session identifier(s)](https://developers.cloudflare.com/api-shield/get-started/#session-identifiers) and [saved your endpoints](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/).

Sequences are currently limited to nine operations in length.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/sequence-analytics/","name":"Sequence Analytics"}}]}
```

---

---
title: Sequence mitigation
description: Enforce expected API request patterns to detect and block malicious sequences.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Sequence mitigation

Sequence mitigation allows you to enforce request patterns for authenticated clients communicating with your API.

You can use sequence rules to establish a set of known behavior for API clients or detect and mitigate malicious behavior.

For example, you may expect that API requests made during a bank funds transfer could conform to the following order in time:

| Order | Method | Path                                   | Description                                                                                                                                    |
| ----- | ------ | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| 1     | GET    | /api/v1/users/{user\_id}/accounts      | user\_id is the active user.                                                                                                                   |
| 2     | GET    | /api/v1/accounts/{account\_id}/balance | account\_id is one of the user’s accounts.                                                                                                     |
| 3     | GET    | /api/v1/accounts/{account\_id}/balance | account\_id is a different account belonging to the user.                                                                                      |
| 4     | POST   | /api/v1/transferFunds                  | This contains a request body detailing an account to transfer funds from, an account to transfer funds to, and an amount of money to transfer. |

You may want to enforce that an API user requests `GET /api/v1/users/{user_id}/accounts` before `GET /api/v1/accounts/{account_id}/balance` and that you request `GET /api/v1/accounts/{account_id}/balance` before `POST /api/v1/transferFunds`.

Using sequence mitigation, you can enforce that request pattern with two new sequence mitigation rules.

Note

You can create sequence mitigation rules for a sequence even if the sequence is not listed in [Sequence Analytics](https://developers.cloudflare.com/api-shield/security/sequence-analytics/).

## Process

You can [create a sequence rule](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/manage-sequence-rules/) to enforce behavior on your API over time using one of two approaches.

A positive security model blocks users who make API requests outside of your expected patterns. A negative security model blocks users who perform a known malicious sequence of API calls.

Sequence rules built via the Cloudflare dashboard using API Shield rules utilize a lookback window to match endpoints in the sequence. The rule will match as long as both endpoints are found within [10 requests](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/#request-limitations) (to endpoints within Endpoint Management) of each other and made within [10 minutes](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/#time-limitations) of each other.

Note

Contact your account team if the default lookback window is not sufficient for you.

If you want to add multiple endpoints, ignore the lookback window, and configure time-based constraints, refer to [Sequence mitigation custom rules](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/custom-rules/).

In the bank funds transfer example, enforcing that a user requests `GET /api/v1/accounts/{account_id}/balance` before `POST /api/v1/transferFunds` is considered a positive security model, since a user may only perform a funds transfer after listing an account balance.

A negative security model may be useful if you see abusive behavior that is outside the norm of your application and you need to stop the requests while researching the correct positive security model to implement.

For example, if there was an authorization bug that allowed users to iterate through other users' profiles that contain account numbers via `GET /api/v1/users/{var1}/profile` and then a user tries to make fraudulent funds transfers, you could create a rule to block or log the sequence `GET /api/v1/users/{var1}/profile` to `POST /api/v1/transferFunds`.

## Limitations

### Endpoint Management

To track requests to API endpoints, they must be added to [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/). Add your endpoints to endpoint management via [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/), [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), or [manually](https://developers.cloudflare.com/api-shield/management-and-monitoring/#add-endpoints-manually) through the Cloudflare dashboard.

### Session Identifiers

API Shield uses your configured session identifier to track sessions. You must configure a session identifier that is unique per end user of your API in order for sequence mitigation to function as expected.

### Request limitations

By default, API Shield stores the current and previous nine requested endpoints by each individual API user identified through the session identifier. Contact your account team if the default lookback window is not sufficient for you.

Sequence mitigation further de-duplicates requests to the same endpoint while building the sequence.

To illustrate, in the original [sequence example](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/) listed above, sequence mitigation would store the following sequence:

1. `GET /api/v1/users/{user_id}/accounts`
2. `GET /api/v1/accounts/{account_id}/balance`
3. `POST /api/v1/transferFunds`

Sequence mitigation de-duplicated the two requests to `GET /api/v1/accounts/{account_id}/balance` and stored them as a single request.

### Time limitations

Sequence mitigation rules have a lookback period of 10 minutes. Any two requests using the same session identifier extend the sequence if they happen no further than 10 minutes apart. A request that happens more than 10 minutes after the previous one starts a new sequence.

For example, if you create a rule requiring one endpoint to be requested before another, and more than 10 minutes elapses between the two requests, the rule will not match.

## Availability

Sequence mitigation is currently in a closed beta and is only available for Enterprise customers. If you would like to be included in the beta, contact your account team.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/sequence-mitigation/","name":"Sequence mitigation"}}]}
```

---

---
title: Configure sequence mitigation via the API
description: Build and configure sequence mitigation rules using the Cloudflare API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configure sequence mitigation via the API

Configuring sequence mitigation via the API consists of building a rule object by choosing the sequence and setting the type of rule and its action.

Example of a rule object

```

{

    "id": "d4909253-390f-4956-89fd-92a5b0cd86d8",

    "title": "<RULE_TITLE>",

    "kind": "allow",

    "action": "block",

    "sequence": [

     "0d9bf70c-92e1-4bb3-9411-34a3bcc59003",

     "b704ab4d-5be0-46e0-9875-b2b3d1ab42f9"

    ],

    "priority": 0,

    "last_updated": "2023-07-24T12:06:51.796286Z",

    "created_at": "2023-07-24T12:06:51.796286Z"

}


```

This rule enforces that a request to endpoint `0d9bf70c-92e1-4bb3-9411-34a3bcc59003` must come before a request to endpoint `b704ab4d-5be0-46e0-9875-b2b3d1ab42f9`.

Otherwise, the request to endpoint `b704ab4d-5be0-46e0-9875-b2b3d1ab42f9` is blocked.

### Fields

| Field name    | Description                                                                                                                                                                                                                                           | Possible Values                                                | Example                                                                            |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| id            | An opaque identifier that identifies a rule.                                                                                                                                                                                                          | A UUID                                                         | "d4909253-390f-4956-89fd-92a5b0cd86d8"                                             |
| title         | A string that helps to identify the rule.                                                                                                                                                                                                             | A value between 1 and 50 characters                            | "Allow checkout sequence"                                                          |
| kind          | Defines the semantics of this rule. Block rules have a negative security model and allow to explicitly deny a sequence. Allow rules have a positive security model and deny everything but the configured sequence.                                   | block, allow                                                   | "block"                                                                            |
| action        | What firewall action should we do when the rule matches.                                                                                                                                                                                              | block,log                                                      | "log"                                                                              |
| sequence      | Denotes the operations (from Endpoint Management) that make up the sequence for this rule. We currently only support sequences of length two. The first operation will be the starting endpoint and the second operation will be the ending endpoint. | An array with two valid operation IDs from Endpoint Management | \["0d9bf70c-92e1-4bb3-9411-34a3bcc59003", "b704ab4d-5be0-46e0-9875-b2b3d1ab42f9"\] |
| priority      | Denotes the precedence of this rule in relation to all other rules. Rules with a higher priority value are evaluated before those with a lower value. If two rules have the same priority, they are evaluated in the order in which they were added.  | A valid integer                                                | 10                                                                                 |
| last\_updated | When this rule was last changed.                                                                                                                                                                                                                      | A date string                                                  | 2023-05-02T12:06:51.796286Z                                                        |
| created\_at   | When this rule was created.                                                                                                                                                                                                                           | A date string                                                  | 2023-05-02T12:06:51.796286Z                                                        |

You can find an endpoint's operation ID by exporting the schema in [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/#export-a-schema) or via the [API](https://developers.cloudflare.com/api/resources/api%5Fgateway/subresources/operations/methods/list/).

### List sequence rules

Use the `GET` command to list rules.

cURL command

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/seqrules"


```

### Add a single sequence rule

Use the `POST` command to create a single rule.

This adds a single rule to all existing rules. Priority can be used to place the rule between, before, or after another rule.

The response will reflect the rule that has been written with its ID. In case something is not right with the rule, an appropriate error message with a `json` path pointing towards the issue will be provided.

Example using cURL

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/seqrules/rules" \

--header "Content-Type: application/json" \

--data '{

  "title": "string",

  "kind": "block",

  "action": "block",

  "sequence": [

    "0d9bf70c-92e1-4bb3-9411-34a3bcc59003",

    "b704ab4d-5be0-46e0-9875-b2b3d1ab42f9"

  ],

  "priority": 0

}'


```

### Add multiple sequence rules

Use the `PUT` command to set up new rules in bulk.

This will overwrite any existing rules and replace them with the rules specified in the body. Setting an empty array for the rules removes all rules.

The response will reflect the rules that have been written with their IDs in case something is not right with the rules, an appropriate error message with a `json` path pointing towards the issue will be provided.

Example using cURL

```

curl --request PUT "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/seqrules" \

--header "Content-Type: application/json" \

--data '{

  "rules": [

    {

      "title": "<RULE_TITLE>",

      "kind": "block",

      "action": "block",

      "sequence": [

        "0d9bf70c-92e1-4bb3-9411-34a3bcc59003",

        "b704ab4d-5be0-46e0-9875-b2b3d1ab42f9"

      ],

      "priority": 0

    }

  ]

}'


```

### Delete a rule

Use the `DELETE` command with its rule ID to delete a rule.

cURL command

```

curl --request DELETE "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/seqrules/rules/d4909253-390f-4956-89fd-92a5b0cd86d8"


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/sequence-mitigation/","name":"Sequence mitigation"}},{"@type":"ListItem","position":5,"item":{"@id":"/api-shield/security/sequence-mitigation/api/","name":"Configure sequence mitigation via the API"}}]}
```

---

---
title: Sequence mitigation custom rules
description: Write custom rules that match valid or invalid API request sequences.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Sequence mitigation custom rules

API Shield sequence custom rules use the configured API Shield session identifier to track the order of requests a user has made and the time between requests, and makes them available via [Cloudflare Rules](https://developers.cloudflare.com/rules). This allows you to write rules that match valid or invalid sequences.

These rules are similar to [cookie sequence rules](https://developers.cloudflare.com/bots/additional-configurations/sequence-rules/) but have a different set of prerequisites:

* They require [session identifiers](https://developers.cloudflare.com/api-shield/get-started/#session-identifiers) to be set in API Shield.
* Because they require session identifiers, they can only be used on traffic that can be clearly attributed to individual users through session identifiers (authenticated traffic).
* Because Cloudflare stores the user state in memory and not in a cookie, a session's sequence lifetime is limited to 10 minutes.
* You must set up at least one [API sequence rule](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/manage-sequence-rules/) to activate the sequence system.

Rules built using these custom rules are similar to the sequence rules that can be configured [via the API or the Cloudflare dashboard](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/) as they make use of the same underlying technology. However, these custom rules allow for greater flexibility by using free-form logic on top of the recorded sequence and providing access to the full response options that rulesets offers.

## Availability

Note

Sequence mitigation is currently in a closed beta and is only available for Enterprise customers. If you would like to be included in the beta, contact your account team.

These sequence fields are available in:

* [Custom rules](https://developers.cloudflare.com/waf/custom-rules/) (`http_request_firewall_custom` phase)
* [Rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/) (`http_request_ratelimit`)
* [Bulk Redirects](https://developers.cloudflare.com/workers/examples/bulk-redirects/) (`http_request_redirect`)
* [Request Header Transform Rules](https://developers.cloudflare.com/rules/transform/response-header-modification/) (`http_request_late_transform`)

| Field name                             | Description                                                                                                                                                                                                                                                                  | Example value                          |
| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
| cf.sequence.current\_opString          | This field contains the ID of the operation that matches the current request. If the current request does not match any operations defined in Endpoint Management, it will be an empty string.                                                                               | c821cc00                               |
| cf.sequence.previous\_opsArray<String> | This field contains an array of the prior operation IDs in the sequence, ordered from most to least recent. It does not include the current request.  If an operation is repeated, it will appear multiple times in the sequence.                                            | \["f54dac32", "c821cc00", "a37dc89b"\] |
| cf.sequence.msec\_since\_opMap<Number> | This field contains a map where the keys are operation IDs and the values are the number of milliseconds since that operation has most recently occurred.  This does not include the current request or operation as it only factors in previous operations in the sequence. | {"f54dac32": 1000, "c821cc00": 2000}   |

## Build a sequence custom rule

* [  New dashboard ](#tab-panel-6587)
* [ Old dashboard ](#tab-panel-6588)

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. To create a new empty rule, select **Create rule** \> **Custom rules**.
3. Enter a descriptive name for the rule in **Rule name**.
4. Under **When incoming requests match**, use the **Field** drop-down list to filter by **Sequences** and select from:  
   * Current Operation  
   * Previous Operations  
   * Elapsed time
5. Under **Value**, select the edit icon to use Builder and build a sequence on the side panel.
6. Under **Select a hostname for this sequence**, choose all or a specific hostname from the dropdown list. Optionally, you can use the search bar to search for a specific hostname.
7. From the **Methods** dropdown list, choose all methods or a specific request method.
8. Select the checkbox for each endpoint in the order that you want them to appear in the sequence.
9. Set the time to complete.
10. Select **Save**.
11. Under **Then take action**, select the rule action in the **Choose action** dropdown. For example, selecting _Block_ tells Cloudflare to refuse requests that match the conditions you specified.
12. (Optional) If you selected the _Block_ action, you can configure a custom response.
13. Under **Place at**, select the order of when the rule will fire.
14. To save and deploy your rule, select **Deploy**. If you are not ready to deploy your rule, select **Save as Draft**.

Note

The fields in the custom rule are populated as a grouped sequence based on the values that you entered on Builder.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **WAF** \> **Custom rules**.
3. To create a new empty rule, select **Create rule**.
4. Enter a descriptive name for the rule in **Rule name**.
5. Under **When incoming requests match**, use the **Field** drop-down list and select:  
   * Current Operation  
   * Previous Operations  
   * Elapsed time
6. Under **Value**, build a sequence by selecting a hostname for the sequence.
7. Select the checkbox for each endpoint in the order that you want them to appear in the sequence.
8. Set the time to complete.
9. Select **Save**.
10. Under **Then take action**, select the rule action in the **Choose action** dropdown. For example, selecting _Block_ tells Cloudflare to refuse requests that match the conditions you specified.
11. (Optional) If you selected the _Block_ action, you can configure a custom response.
12. Under **Place at**, select the order of when the rule will fire.
13. To save and deploy your rule, select **Deploy**. If you are not ready to deploy your rule, select **Save as Draft**.

### Example rules

Each saved endpoint will have an endpoint ID visible in its details page in Endpoint Management in the form of a UUID. The references below (`aaaaaaaa`, `bbbbbbbb`, and `cccccccc`) are the first eight characters of the endpoint ID.

The visitor must wait more than 2 seconds after requesting endpoint `aaaaaaaa` before requesting endpoint `bbbbbbbb`:

```

cf.sequence.current_op eq "bbbbbbbb" and

cf.sequence.msec_since_op["aaaaaaaa"] ge 2000


```

The visitor must request endpoints `aaaaaaaa`, then `bbbbbbbb`, then `cccccccc` in that exact order:

```

cf.sequence.current_op eq "cccccccc" and

cf.sequence.previous_ops[0] == "bbbbbbbb" and

cf.sequence.previous_ops[1] == "aaaaaaaa"


```

The visitor must request endpoint `aaaaaaaa` before endpoint `bbbbbbbb`, but endpoint `aaaaaaaa` can be anywhere in the previous 10 requests:

```

cf.sequence.current_op eq "bbbbbbbb" and

any(cf.sequence.previous_ops[*] == "aaaaaaaa")


```

The visitor must request either endpoint `aaaaaaaa` before endpoint `bbbbbbbb`, or endpoint `cccccccc` before endpoint `bbbbbbbb`:

```

(cf.sequence.current_op eq "bbbbbbbb" and

any(cf.sequence.previous_ops[*] == "aaaaaaaa")) or

(cf.sequence.current_op eq "bbbbbbbb" and

any(cf.sequence.previous_ops[*] == "cccccccc"))


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/sequence-mitigation/","name":"Sequence mitigation"}},{"@type":"ListItem","position":5,"item":{"@id":"/api-shield/security/sequence-mitigation/custom-rules/","name":"Sequence mitigation custom rules"}}]}
```

---

---
title: Manage sequence rules
description: Create and manage sequence rules in the dashboard or via WAF custom rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Manage sequence rules

Cloudflare recommends creating sequence rules using WAF custom rules. Refer to the [sequence custom rules documentation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/custom-rules/) for more information.

Note

Sequence mitigation is currently in a closed beta and is only available for Enterprise customers. If you would like to be included in the beta, contact your account team.

## Create a sequence rule

* [  New dashboard ](#tab-panel-6589)
* [ Old dashboard ](#tab-panel-6590)

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. Select **Create rule** and choose **API sequence rules**.
3. Name your rule.
4. Select a starting endpoint. This is the endpoint that you expect users to hit first in their request flow when using your API.  
   * Choose a hostname to display the list of endpoints for that hostname.  
   * Choose an endpoint.  
   * Select **Set as starting endpoint**.
5. Select a final endpoint. This is the endpoint you are targeting for protection.  
   * Choose a hostname to display the list of endpoints for that hostname.  
   * Choose an endpoint.  
   * Select **Set as ending endpoint**.
6. Choose an action that corresponds to the security model type:  
   * **Allow**: This will create a positive security model by defining approved sequences on your API.  
   * **Log** / **Block**: This will test or enforce a negative security model defining known bad sequences on your API.  
   Note  
   If you chose **Allow**, select whether to log or block the request to the final endpoint when users do not first request the starting endpoint in the sequence.
7. Select **Create rule**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **API Shield** \> **API Rules**.
3. Select **Create sequence rule**.
4. Name your rule.
5. Select a starting endpoint. This is the endpoint that you expect users to hit first in their request flow when using your API.  
   * Choose a hostname to display the list of endpoints for that hostname.  
   * Choose an endpoint.  
   * Select **Set as starting endpoint**.
6. Select a final endpoint. This is the endpoint you are targeting for protection.  
   * Choose a hostname to display the list of endpoints for that hostname.  
   * Choose an endpoint.  
   * Select **Set as ending endpoint**.
7. Choose an action that corresponds to the security model type:  
   * **Allow**: This will create a positive security model by defining approved sequences on your API.  
   * **Log** / **Block**: This will test or enforce a negative security model defining known bad sequences on your API.  
   Note  
   If you chose **Allow**, select whether to log or block the request to the final endpoint when users do not first request the starting endpoint in the sequence.
8. Select **Create rule**.

## Edit a sequence rule

You also have the option to edit an existing rule by selecting it on the rule list. You can rename your rule, adjust the starting and ending endpoint order, modify the endpoint, and change the action of the rule.

## Reprioritize a sequence rule

You can change the priority order of your rules by selecting and dragging the rules on the list.

You can also explicitly set a priority order by selecting the three dots on your rule and choosing **Move to…** where you can set the new priority in the resulting modal window.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/sequence-mitigation/","name":"Sequence mitigation"}},{"@type":"ListItem","position":5,"item":{"@id":"/api-shield/security/sequence-mitigation/manage-sequence-rules/","name":"Manage sequence rules"}}]}
```

---

---
title: Volumetric Abuse Detection
description: Set up adaptive, per-session rate limiting for API endpoints with Volumetric Abuse Detection.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Volumetric Abuse Detection

Cloudflare Volumetric Abuse Detection generates per-endpoint, per-session rate limit recommendations that adjust automatically as your traffic patterns change.

Cloudflare looks for endpoint abuse based on user traffic to individual endpoints.

For example, your API might see different levels of traffic to a `/reset-password` endpoint than a `/login` endpoint. Additionally, your `/login` endpoint might see higher than average traffic after a successful marketing campaign.

These two scenarios speak to the limitations of traditional rate limiting. Not only does traffic vary between endpoints, but it also can vary over time for the same endpoint. Volumetric Abuse Detection solves these problems using unsupervised learning (analyzing traffic patterns without predefined rules) to develop separate baselines for each endpoint and adjust to changes in user behavior over time.

Volumetric Abuse Detection rate limits are generated on a per-session basis rather than per IP address. This reduces false positives when traffic to your API increases, because rate limits track individual sessions rather than shared IP addresses.

Volumetric Abuse Detection rate limits are a way to prevent blatant volumetric abuse while minimizing false positives. If you are trying to prevent abusive bot traffic altogether, refer to Cloudflare's [Bot solutions](https://developers.cloudflare.com/bots/).

## Process

Volumetric Abuse Detection analyzes your API's individual session traffic statistics to recommend per-endpoint, per-session rate limits.

To access your endpoints:

Old dashboard: **Security** \> **API Shield** \> **Endpoint Management**

New dashboard: **Security** \> **Web Assets** \> **Endpoints**

Recommendations will continue to update if your traffic pattern changes.

### Requirements

Volumetric Abuse Detection generates rate limit thresholds only after collecting enough traffic data to produce reliable recommendations. If recommendations are missing for a discovered endpoint, the traffic likely failed to meet the necessary criteria.

Thresholds are suggested only for endpoints that satisfy all of the following requirements within the last seven days (or since initial discovery):

* The endpoint must receive sufficient valid traffic (traffic that meets the [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/#requirements) criteria). Intermittent or erratic traffic may prevent suggestions.
* The endpoint must be accessed by at least 50 distinct sessions in any 24-hour period during the last seven days.
* [Session identifiers](https://developers.cloudflare.com/api-shield/get-started/#to-set-up-session-identifiers), such as an authorization token available as a request header or cookie, must be configured to allow Cloudflare to accurately detect individual sessions and perform the required per-session rate analysis.

After adding a session identifier, allow 24 hours for rate limit recommendations to appear on endpoints in the Cloudflare dashboard.

### Rate limiting recommendation calculation

Select an endpoint row in **Endpoints** to view its rate limit recommendation. The detail view shows the overall recommended value and percentile-based values (p50, p90, p99).

Percentile values

Percentile values describe what portion of your traffic falls below a threshold. For example, if your p90 value is `83`, then 90% of your sessions had maximum request rates less than 83 requests per 10 minutes.

Cloudflare recalculates the recommended value throughout the day based on requests from the last 24 hours. The recommendation may not change if your traffic profile remains consistent.

Cloudflare recommends using the overall rate limit recommendation rather than a single percentile value. The overall recommendation accounts for variation across all your API sessions. Choosing a single percentile value may cause false positives due to a high number of outliers.

In **Endpoints**, you can review the confidence level for each recommendation and how many unique sessions were observed over the last seven days. In general, endpoints with fewer unique sessions and high variability of user behavior will have lower confidence scores.

Implementing low confidence rate limits can still be helpful to prevent API abuse. If the confidence level is low, start your rate limit rule in `log` mode and observe violations for false positives before switching to `block`.

### Create rate limits

Refer to the [Rules documentation](https://developers.cloudflare.com/waf/rate-limiting-rules/create-zone-dashboard/) for more information on how to create an Advanced Rate Limiting rule.

## API

[Rate limit recommendations are available via the API](https://developers.cloudflare.com/api/resources/api%5Fgateway/subresources/operations/methods/get/) if you would like to dynamically update rate limits over time.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Account API Gateway`
* `Account API Gateway Read`
* `Domain API Gateway`
* `Domain API Gateway Read`

Retrieve information about an operation

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/api_gateway/operations/$OPERATION_ID" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

## Special cases

### Rate limit by user (JWT claim)

You can rate limit requests based on any claim inside of a JSON Web Token (JWT), such as:

* Registered claims like `aud` or `sub`
* Custom claims like `userEmail`, including nested custom claims like `user.email`

Rate limiting based on JWT claim values will only work on valid JSON Web Tokens. If you do not block invalid JSON Web Tokens on your path, the [JWT claims will all be counted and possibly blocked](https://developers.cloudflare.com/waf/rate-limiting-rules/parameters/#missing-field-versus-empty-value) if high traffic is detected in the Point of Presence (PoP).

You must also count the JWT claim that uniquely identifies the user. If you select a claim that is the same for many of your users, their rate limits will all be counted together.

### Rate limit by user tier

If you offer multiple tiers on your website or application and you want to enforce rate limiting based on the tiers, such as:

* If `"aud": "free-tier"`, rate limit to five requests per minute.
* If `"aud": "premium-tier"`, rate limit to 50 requests per minute.

You can follow the rate limiting rule example below:

Example rule expression

```

(http.request.method eq "GET" and

http.host eq "<YOUR_DOMAIN>" and

http.request.uri.path matches "</EXAMPLE_PATH>" and

lookup_json_string(http.request.jwt.claims["<JWT_TOKEN_CONFIGURATION_ID>"][0], "aud") eq "free-tier"


```

## Limitations

API Shield will always calculate recommendations when session identifiers are configured. To enable session-based rate limits, [subscribe to Advanced Rate Limiting](https://developers.cloudflare.com/waf/rate-limiting-rules/#availability).

## Availability

Volumetric Abuse Detection is only available for Enterprise customers. If you are an Enterprise customer interested in this product, contact your account team.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/volumetric-abuse-detection/","name":"Volumetric Abuse Detection"}}]}
```

---

---
title: Configure Vulnerability Scanner via the API
description: Test API endpoints for BOLA and other vulnerabilities using the Cloudflare API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configure Vulnerability Scanner via the API

Use Cloudflare Vulnerability Scanner to test your API endpoints for vulnerabilities such as Broken Object Level Authorization (BOLA). This guide explains how to run your first vulnerability scan using the Cloudflare API.

## Prerequisites

You must have:

* At least one zone in the account.
* An OpenAPI schema describing the API you want to scan.
* API credentials for your target. The scanner needs to authenticate as different users to test for BOLA vulnerabilities.

---

## Process

### Create an API token

All API requests use the base URL `https://api.cloudflare.com/client/v4/` and authenticate with a `Bearer` token in the `Authorization` header.

[Create an API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) in the Cloudflare dashboard with the following [permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/) scoped to the target account: **Account** \> **API Gateway** \> **Edit**

Save your API token and Account Tag from your account's **Overview** page in the Cloudflare dashboard as environment variables to use in the following commands.

Terminal window

```

export CLOUDFLARE_API_TOKEN="<YOUR_API_TOKEN>"

export ACCOUNT_ID="<YOUR_ACCOUNT_ID>"


```

### Create a target environment

A target environment defines what the scanner should scan. Currently, the only supported target type is zone.

Find your Zone Tag on the zone's **Overview** page in the Cloudflare dashboard and export it.

Terminal window

```

export ZONE_TAG="<YOUR_ZONE_TAG>"


```

Use the following `POST` request to create the target environment.

cURL command

```

curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/target_environments" \

  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \

  --header "Content-Type: application/json" \

  --data '{

    "name": "Production API",

    "description": "Main production zone for API scanning",

    "target": {

      "type": "zone",

      "zone_tag": "'"${ZONE_TAG}"'"

    }

  }'


```

Save the target environment ID from the response into a variable `TARGET_ENV_ID`.

(Optional) You can verify your target environment by making a `GET` request to the following URL.

```

https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/target_environments/${TARGET_ENV_ID}


```

### Create credential sets

Currently, the scanner supports a BOLA scan. This requires two sets of credentials:

* Owner: A legitimate user who owns the resources being tested.
* Attacker: A different legitimate user who should not have access to the owner's resources.

The scanner authenticates as both users and checks whether the attacker can access the owner's resources. Each set of credentials is organized into a credential set containing one or more credentials.

Use the following `POST` requests to create an Owner credential set and an Attacker credential set.

Owner credential set

```

curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/credential_sets" \

  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \

  --header "Content-Type: application/json" \

  --data '{ "name": "Owner Credentials" }'


# Export the ID from the response

export OWNER_CRED_SET_ID="<OWNER_CRED_SET_ID>"


```

Attacker credential set

```

curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/credential_sets" \

  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \

  --header "Content-Type: application/json" \

  --data '{ "name": "Attacker Credentials" }'


# Export the ID from the response

export ATTACKER_CRED_SET_ID="<ATTACKER_CRED_SET_ID>"


```

### Add credentials to each credential set

A credential describes a single authentication token or session value that the scanner attaches to its requests.

Note

The value field is `write-only` and is never returned by the API.

Use the following `POST` requests to add the owner and attacker's credentials to each set.

Owner's credential (Header)

```

curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/credential_sets/${OWNER_CRED_SET_ID}/credentials" \

  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \

  --header "Content-Type: application/json" \

  --data '{

    "name": "Owner Bearer Token",

    "location": "header",

    "location_name": "authorization",

    "value": "Bearer eyJhbGciOiJSUzI1NiIs...owner-token"

  }'


```

Attacker's credential (Cookie)

```

curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/credential_sets/${ATTACKER_CRED_SET_ID}/credentials" \

  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \

  --header "Content-Type: application/json" \

  --data '{

    "name": "Attacker Session Cookie",

    "location": "cookie",

    "location_name": "session_id",

    "value": "attacker-session-token-value"

  }'


```

(Optional) You can list all credentials in a set using a `GET` request to the following URL.

```

https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/credential_sets/<CRED_SET_ID>/credentials


```

### Start a scan

With your target environment and two credential sets ready, you can start a BOLA scan.

Ensure your OpenAPI schema is formatted as a string. For example, using `jq`.

Terminal window

```

OPEN_API_SCHEMA=$(jq -c . < openapi.json)


```

Use the following `POST` request to initiate the scan.

cURL command

```

curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans" \

  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \

  --header "Content-Type: application/json" \

  --data "$(jq -n \

    --arg te_id "$TARGET_ENV_ID" \

    --arg schema "$OPEN_API_SCHEMA" \

    --arg owner "$OWNER_CRED_SET_ID" \

    --arg attacker "$ATTACKER_CRED_SET_ID" \

    '{

      target_environment_id: $te_id,

      scan_type: "bola",

      open_api: $schema,

      credential_sets: { owner: $owner, attacker: $attacker }

    }')"


```

Save the scan ID from the response.

Terminal window

```

export SCAN_ID="<SCAN_ID>"


```

You can check the status of your scan using a `GET` request.

cURL command

```

curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans/${SCAN_ID}" \

  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}"


```

### Retrieve the scan report

Once a scan has status `completed`, a report is available containing detailed findings for the vulnerabilities tested.

cURL command

```

curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans/${SCAN_ID}" \

  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}"


```

Note

When the scan has not yet completed, the API returns the result as `null`.

You may find it easier to summarize the report results with `jq`.

Terminal window

```

curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans/${SCAN_ID}" \

  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" | jq '.result.report.report.tests[] | {test_verdict: .verdict, steps: [.steps | to_entries[] | {step: (.key + 1), method: .value.request.method, url: .value.request.url, role: .value.request.credential_set.role, status: (if .value.errors | length > 0 then "error" else "ok" end)}]}'


```

Adding the `jq` command will summarize the output. In the following example, the attacker successfully accessed the `DELETE` endpoint in step 3.

```

{

  "test_verdict": "warning",

  "steps": [

    {

      "step": 1,

      "method": "POST",

      "url": "https://api.example.com/v1/orders",

      "role": "owner",

      "status": "ok"

    },

    {

      "step": 2,

      "method": "GET",

      "url": "https://api.example.com/v1/orders",

      "role": "attacker",

      "status": "ok"

    },

    {

      "step": 3,

      "method": "DELETE",

      "url": "https://api.example.com/v1/orders/bdc64e8a-deec-4374-92c0-4fe91d1650bb",

      "role": "attacker",

      "status": "error"

    }

  ]

}


```

#### Example polling pattern

A common pattern is to poll the scan status until it completes, then fetch the report.

Example

```

while true; do

  STATUS=$(curl --silent \

    "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans/${SCAN_ID}" \

    --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" | jq -r '.result.status // empty')


  echo "Scan status: ${STATUS:-unknown}"


  case "$STATUS" in

    completed) echo "Scan finished. Fetching report..."; break ;;

    failed)    echo "Scan failed." >&2; exit 1 ;;

    *)         sleep 10 ;;

  esac

done


curl --silent \

"https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans/${SCAN_ID}/report" \

  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" | jq .


```

---

## Limitations

During the open beta, if you have large OpenAPI specs, you may want to optimize your specs for the scanner.

The AI model used to build a plan for scanning your API has a 128k token context limit. This approximates to 40 to 60kB of file size on disk. If your schema is larger than this size, you may need to split your schema into smaller files.

Similarly, you may see more thorough scan results by creating individual OpenAPI files by semantic use case. For example, if your application supports account modification, social sharing, and personal favoriting, splitting your spec into multiple files per these use cases may show increased test coverage during the beta.

---

## Availability

The vulnerability scanner is currently only available for Enterprise API Shield customers. Cloudflare will add more scan types in the future and increase the availability of the scanner at that time.

---

## Reference

### Credential locations

When creating credentials, the `location` field determines where the scanner attaches the credential during requests.

| Location | location\_name      | Example use case                          |
| -------- | ------------------- | ----------------------------------------- |
| header   | An HTTP header name | Authorization header with a Bearer token. |
| cookie   | A cookie name       | session\_id cookie with a session token.  |

A credential set can contain multiple credentials. For example, an API that requires both a `Bearer` token in the `Authorization` header and a `CSRF` token in the `X-CSRF-Token` header would have two separate credentials configured in its set.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/security/","name":"Security"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/security/vulnerability-scanner/","name":"Configure Vulnerability Scanner via the API"}}]}
```

---

---
title: API Gateway
description: Use Cloudflare as your API gateway for security, management, and routing.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# API Gateway

Cloudflare API Shield provides API security, management tools, and integration with the Cloudflare Developer Platform for building new APIs.

* **Security**: Protect APIs with JWT validation, mutual TLS (mTLS) authentication, schema validation, and defenses against the [OWASP Top 10 API Security risks ↗](https://owasp.org/www-project-api-security/).
* **Management and monitoring**: Use endpoint management, analytics, and routing tools to streamline API operations. Monitor risks with Posture Management and gain visibility through Security Analytics.
* **Development**: Build and deploy APIs using the Cloudflare Developer Platform with its serverless infrastructure and developer tools.

## Cloudflare as your API Gateway

### API security features

* **Protection Against OWASP Top 10 API Security risks**: Mitigate common API vulnerabilities, including injection attacks and improper asset management.

### Management and Monitoring tools

* **[Endpoint management](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/)**: Gain visibility into your API endpoints, including discovery of shadow APIs and monitoring of active endpoints.
* **[Analytics and logging](https://developers.cloudflare.com/api-shield/security/sequence-analytics/)**: Access detailed analytics and logs to monitor API usage, performance, and security events.
* **[API Routing](https://developers.cloudflare.com/api-shield/management-and-monitoring/api-routing/)**: Optimize API performance and reliability with secure routing.
* **[Posture Management](https://developers.cloudflare.com/api-shield/security/authentication-posture/)**: Monitor API Authentication status and receive alerts for common API risks.

### Build APIs with Cloudflare’s Developer Platform

The [Cloudflare Developer Platform ↗](https://www.cloudflare.com/developer-platform/) offers a serverless execution environment, allowing you to build and deploy new APIs without the need to manage infrastructure. Its benefits include:

* **Global scalability**: Deploy APIs across Cloudflare's global network for low latency and high availability.
* **Integrated services**: Use storage, databases, and AI tools alongside your APIs.
* **Developer tools**: Build with frameworks and tools that support the API development workflow.

## Get started

To begin using Cloudflare API Shield, refer to our [Get started](https://developers.cloudflare.com/api-shield/get-started/) guide.

For detailed instructions and additional resources, refer to the [API Shield documentation](https://developers.cloudflare.com/api-shield/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/api-gateway/","name":"API Gateway"}}]}
```

---

---
title: Glossary
description: Definitions for terms used across API Shield documentation.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Glossary

Review the definitions for terms used across Cloudflare's API Shield documentation.

| Term               | Definition                                                                                                                                                    |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| API call           | Also known as an API request. An API call is a message sent to a server asking an API to provide a service or information.                                    |
| API endpoint       | The API endpoint is the location where API calls or requests are fulfilled. API Shield defines endpoints as a host, method, and path tuple.                   |
| API schema         | The API schema defines which API requests are valid based on several request properties like target endpoint, path or query variable format, and HTTP method. |
| session identifier | A session identifier is a unique identifier that a website assigns to identify a specific user for the duration of their visit.                               |
| source endpoint    | The source endpoint is the endpoint managed by API Shield in Endpoint Management by its routing feature.                                                      |
| target endpoint    | The target endpoint is the ultimate destination that a request is sent to by API Shield's routing feature.                                                    |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/glossary/","name":"Glossary"}}]}
```

---

---
title: Changelog
description: Track the latest updates and changes to API Shield features.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Changelog

[ Subscribe to RSS ](https://developers.cloudflare.com/changelog/rss/api-shield.xml) 

## 2026-03-23

  
**Web Assets fields now available in GraphQL Analytics API**   

Two new fields are now available in the `httpRequestsAdaptive` and `httpRequestsAdaptiveGroups` [GraphQL Analytics API](https://developers.cloudflare.com/analytics/graphql-api/) datasets:

* `webAssetsOperationId` — the ID of the [saved endpoint](https://developers.cloudflare.com/api-shield/management-and-monitoring/) that matched the incoming request.
* `webAssetsLabelsManaged` — the [managed labels](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/#managed-labels) mapped to the matched operation at the time of the request (for example, `cf-llm`, `cf-log-in`). At most 10 labels are returned per request.

Both fields are empty when no operation matched. `webAssetsLabelsManaged` is also empty when no managed labels are assigned to the matched operation.

These fields allow you to determine, per request, which Web Assets operation was matched and which managed labels were active. This is useful for troubleshooting downstream security detection verdicts — for example, understanding why [AI Security for Apps](https://developers.cloudflare.com/waf/detections/ai-security-for-apps/) did or did not flag a request.

Refer to [Endpoint labeling service](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/#analytics) for GraphQL query examples.

## 2026-03-09

  
**New Vulnerability Scanner for API Shield**   

Introducing Cloudflare's Web and API Vulnerability Scanner (Open Beta)

Cloudflare is launching the [Open Beta of the **Web and API Vulnerability Scanner** ↗](https://blog.cloudflare.com/vulnerability-scanner) for all [API Shield](https://developers.cloudflare.com/api-shield/) customers. This new, stateful Dynamic Application Security Testing (DAST) platform helps teams proactively find logic flaws in their APIs.

The initial release focuses on detecting Broken Object Level Authorization (BOLA) vulnerabilities by building API call graphs to simulate attacker and owner contexts, then testing these contexts by sending real HTTP requests to your APIs.

The scanner is now available via the Cloudflare API. To scan, set up your target environment, owner and attacker credentials, and upload your OpenAPI file with response schemas. The scanner will be available in the Cloudflare dashboard in a future release.

**Access**: This feature is only available to API Shield subscribers via the Cloudflare API. We hope you will use the API for programmatic integration into your CI/CD pipelines and security dashboards.

**Documentation**: Refer to the [developer documentation](https://developers.cloudflare.com/api-shield/security/vulnerability-scanner/) to start scanning your endpoints today.

## 2025-11-25

  
**New Zombie API detection for API Shield**   

API Shield now automatically detects zombie endpoints — saved endpoints that have not received traffic for an extended period. When detected, the `cf-risk-zombie` [risk label](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/#risk-labels) is applied.

The scan runs daily alongside existing risk scans. Endpoints are labeled after 32 days without traffic.

Zombie endpoints may indicate deprecated or forgotten API surface area that could pose a security risk. Review these endpoints and consider removing them from Endpoint Management if they are no longer in use. Also consider using a [fallthrough rule](https://developers.cloudflare.com/api-shield/security/schema-validation/#add-validation-by-adding-a-fallthrough-rule) to prevent communication with endpoints removed from Endpoint Management.

## 2025-11-12

  
**New BOLA Vulnerability Detection for API Shield**   

Now, API Shield automatically searches for and highlights **Broken Object Level Authorization (BOLA) attacks** on managed API endpoints. API Shield will highlight both BOLA enumeration attacks and BOLA pollution attacks, telling you what was attacked, by who, and for how long.

You can find these attacks three different ways: Security Overview, Endpoint details, or Security Analytics. If these attacks are not found on your managed API endpoints, there will not be an overview card or security analytics suspicious activity card.

![BOLA attack Overview card](https://developers.cloudflare.com/_astro/bola-overview-card.hwcSeAkb_1MwSDq.webp)![BOLA attack Overview drawer](https://developers.cloudflare.com/_astro/bola-overview-drawer.DD2c0bxS_zw6Ec.webp) 

From the endpoint details, you can select **View attack** to find details about the BOLA attacker’s sessions.

![BOLA attack endpoint details](https://developers.cloudflare.com/_astro/bola-endpoint-attack.UQP3MDkp_1Yhqqd.webp) 

From here, select **View in Analytics** to observe attacker traffic over time for the last seven days.

![BOLA attack analytics drawer](https://developers.cloudflare.com/_astro/bola-analytics-drawer.DXzC6EJU_iXjmr.webp) 

Your search will filter to traffic on that endpoint in the last seven days, along with the malicious session IDs found in the attack. Session IDs are hashed for privacy and will not be found in your origin logs. Refer to IP and JA4 fingerprint to cross-reference behavior at the origin.

At any time, you can also start your investigation into attack traffic from Security Analytics by selecting the suspicious activity card.

![Suspicious Activity card](https://developers.cloudflare.com/_astro/bola-suspicious-card._B3GB3s4_STW1N.webp) 

We urge you to take all of this client information to your developer team to research the attacker behavior and ensure any broken authorization policies in your API are fixed at the source in your application, preventing further abuse.

In addition, this release marks the end of the beta period for these scans. All Enterprise customers with API Shield subscriptions will see these new attacks if found on their zone.

## 2025-03-18

  
**New API Posture Management for API Shield**   

Now, API Shield **automatically** labels your API inventory with API-specific risks so that you can track and manage risks to your APIs.

View these risks in [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/) by label:

![A list of endpoint management labels](https://developers.cloudflare.com/_astro/endpoint-management-label.BDmf8Ai1_ZM5mgU.webp) 

...or in [Security Center Insights](https://developers.cloudflare.com/security/security-insights/):

![An example security center insight](https://developers.cloudflare.com/_astro/posture-management-insight.7vB7mzGI_Z1HKoUN.webp) 

API Shield will scan for risks on your API inventory daily. Here are the new risks we're scanning for and automatically labelling:

* **cf-risk-sensitive**: applied if the customer is subscribed to the [sensitive data detection ruleset](https://developers.cloudflare.com/waf/managed-rules/reference/sensitive-data-detection/) and the WAF detects sensitive data returned on an endpoint in the last seven days.
* **cf-risk-missing-auth**: applied if the customer has configured a session ID and no successful requests to the endpoint contain the session ID.
* **cf-risk-mixed-auth**: applied if the customer has configured a session ID and some successful requests to the endpoint contain the session ID while some lack the session ID.
* **cf-risk-missing-schema**: added when a learned schema is available for an endpoint that has no active schema.
* **cf-risk-error-anomaly**: added when an endpoint experiences a recent increase in response errors over the last 24 hours.
* **cf-risk-latency-anomaly**: added when an endpoint experiences a recent increase in response latency over the last 24 hours.
* **cf-risk-size-anomaly**: added when an endpoint experiences a spike in response body size over the last 24 hours.

In addition, API Shield has two new 'beta' scans for **Broken Object Level Authorization (BOLA) attacks**. If you're in the beta, you will see the following two labels when API Shield suspects an endpoint is suffering from a BOLA vulnerability:

* **cf-risk-bola-enumeration**: added when an endpoint experiences successful responses with drastic differences in the number of unique elements requested by different user sessions.
* **cf-risk-bola-pollution**: added when an endpoint experiences successful responses where parameters are found in multiple places in the request.

We are currently accepting more customers into our beta. Contact your account team if you are interested in BOLA attack detection for your API.

Refer to the [blog post ↗](https://blog.cloudflare.com/cloudflare-security-posture-management/) for more information about Cloudflare's expanded posture management capabilities.

## 2025-02-17

**New automatically applied risk labels**

API Shield now automatically labels endpoints with risks due to missing schemas and performance anomalies (spikes in error rates, latency, and body response sizes).

## 2025-01-16

**API Authentication Posture**

Customers will see per-endpoint authentication details inside [Endpoints](https://developers.cloudflare.com/api-shield/management-and-monitoring/) for zones with configured session identifiers.

## 2024-12-19

**Automatically applied endpoint risk labels**

API Shield now automatically labels endpoints with risks due to authentication status and sensitive data detection.

## 2024-11-04

**Endpoint labels**

Customers can now organize their endpoints by use case and custom labels using the [Endpoint labeling service](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/) for easy reference and future machine learning (ML) model training.

## 2024-10-18

**API Shield fields in Custom Rules**

Customers can now use API Shield product feature fields in [custom rules](https://developers.cloudflare.com/waf/custom-rules/), referencing features such as [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/), [session identifiers](https://developers.cloudflare.com/api-shield/get-started/#session-identifiers), and [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/).

## 2024-09-25

**Fallthrough rule for Schema validation 2.0**

Customers can now enable the [Fallthrough Action](https://developers.cloudflare.com/api-shield/security/schema-validation/#add-validation-by-adding-a-fallthrough-rule) for Schema validation 2.0 to block or log requests that do not match the endpoints listed in schemas protected by Schema validation 2.0.

## 2024-08-28

**Increased capacity for Endpoint management and Schema validation**

Endpoint management and Schema validation now support up to 10,000 saved and validated API endpoints.

## 2024-07-08

**API Discovery's hostname variables**

Customers can now see when [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/) groups similar subdomains with the same methods and paths, making it easy to discover and manage APIs that share many vanity domains or subdomains.

## 2024-07-02

**Route API requests using API Routing**

Customers can now route requests to different back-end services through [API Routing](https://developers.cloudflare.com/api-shield/management-and-monitoring/api-routing/), creating a unified front for their APIs distributed across otherwise disparate systems.

## 2024-05-13

**Use JWT claims in Advanced Rate Limiting, Transform Rules, and as session IDs**

Customers can now use the fields inside [JSON Web Tokens (known as claims)](https://developers.cloudflare.com/api-shield/security/jwt-validation/transform-rules/#enhance-transform-rules-with-jwt-claims) as [session identifiers in API Shield](https://developers.cloudflare.com/api-shield/get-started/#session-identifiers), to count values in [Advanced Rate Limiting](https://developers.cloudflare.com/waf/rate-limiting-rules/), and to send on useful information in [Transform Rules](https://developers.cloudflare.com/rules/transform/).

## 2024-04-30

**Build sequence mitigation rules via the Cloudflare dashboard**

Customers can now build [Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/) rules with a new user interface inside the API Shield section of the [Cloudflare dashboard ↗](https://dash.cloudflare.com/).

## 2024-02-23

**Endpoint management supports hostname variables**

Customers can now save endpoints in [Endpoint management](https://developers.cloudflare.com/api-shield/management-and-monitoring/) that contain variables in the hostname. Hostname variables are supported across all product features.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/changelog/","name":"Changelog"}}]}
```

---

---
title: API Routing
description: Route API requests to different back-end services using API Shield Routing.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# API Routing

API Shield Routing allows you to expose a single external API that routes requests to different back-end services, even when those services use different paths or hostnames than your zone.

Note

The term **Source Endpoint** refers to the endpoint managed by API Shield in Endpoint Management. The term **Target Endpoint** refers to the ultimate destination the request is sent to by the Routing feature.

## Process

You must add Source Endpoints to Endpoint Management through established methods, including [uploading a schema](https://developers.cloudflare.com/api-shield/security/schema-validation/#add-validation-by-uploading-a-schema), via [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/), or by [adding manually](https://developers.cloudflare.com/api-shield/management-and-monitoring/#add-endpoints-manually), before creating a route.

To create a route, you will need the operation ID of the Source Endpoint. To find the operation ID in the dashboard:

* [  New dashboard ](#tab-panel-6531)
* [ Old dashboard ](#tab-panel-6532)

1. In the Cloudflare dashboard, go to the **Web Assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Filter the endpoints to find your **Source Endpoint**.
3. Expand the row for your Source Endpoint and note the **operation ID** field.
4. Select the copy icon to copy the operation ID to your clipboard.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Select **Security** \> **API Shield**.
3. Filter the endpoints to find your **Source Endpoint**.
4. Expand the row for your Source Endpoint and note the **operation ID** field.
5. Select the copy icon to copy the operation ID to your clipboard.

Once your Source Endpoints are added to Endpoint Management, use the following steps to create and verify routes on any given operation ID:

### Create a route

* [  New dashboard ](#tab-panel-6533)
* [ Old dashboard ](#tab-panel-6534)

1. In the Cloudflare dashboard, go to the **Web Assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. In **Endpoints**, select an existing endpoint and expand its details.
3. Under **Routing**, select **Create route**.
4. Enter the target URL or IP address to route your endpoint to.
5. Select **Deploy route**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **API Shield**.
3. In **Endpoint Management**, select an existing endpoint and expand its details.
4. Under **Routing**, select **Create route**.
5. Enter the target URL or IP address to route your endpoint to.
6. Select **Deploy route**.

Note

You can reorder path variables if they are present. For example, you can route `/api/{var1}/users/{var2}` to `/{var2}/users/{var1}`. Segments of the path that are not variables may be added or omitted entirely.

You can also edit or delete a route by selecting **Edit route** on an existing route.

### Test a route

After sending a request to your Source Endpoint, you should see the contents of the back-end service as if you called the Target Endpoint directly.

If API Shield returns unexpected results, check your Source Endpoint host, method, and path and [verify the Route](https://developers.cloudflare.com/api-shield/management-and-monitoring/api-routing/#verify-a-route) to ensure the Target Endpoint value is correct.

Note

You may need to wait up to five minutes for Route changes to synchronize across the Cloudflare network.

## Availability

API Shield Routing is currently in an open beta and is only available for Enterprise customers subscribed to API Shield. Enterprise customers who have not purchased API Shield can preview [API Shield as a non-contract service ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/api-shield) in the Cloudflare dashboard or by contacting your account team.

## Limitations

The Target Endpoint cannot be routed to a Worker if the route is to the same zone.

You cannot change the method of a request. For example, a `GET` Source Endpoint will always send a `GET` request to the Target Endpoint.

You must use all of the variables in the Target Endpoint that appear in the Source Endpoint. For example, routing `/api/{var1}/users/{var2}` to `/api/users/{var2}` is not allowed and will result in an error since `{var1}` is present in the Source Endpoint but not in the Target Endpoint.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/management-and-monitoring/","name":"Management and Monitoring"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/management-and-monitoring/api-routing/","name":"API Routing"}}]}
```

---

---
title: Build developer portals
description: Create interactive API documentation portals from saved endpoints or schemas.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Build developer portals

Once your endpoints are saved, API Shield doubles as an API catalog. API Shield can build an interactive documentation portal with the knowledge it has of your APIs, or you can upload a new OpenAPI schema file to build a documentation portal ad-hoc.

To create a developer portal:

* [  New dashboard ](#tab-panel-6535)
* [ Old dashboard ](#tab-panel-6536)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **API abuse**.
3. On **Create a developer portal**, select **Create site**.
4. Upload an OpenAPI v3.0 schema file or choose to select an existing schema from API Shield.  
Note  
If you do not have a schema to upload or to select from a pre-existing schema, export your Endpoint Management schema. For best results, include the learned parameters.  
Only API schemas uploaded to Schema validation 2.0 are available when selecting existing schemas.
5. Select **Download project files** to save a local copy of the files that will be uploaded to Cloudflare Pages. Downloading the project files can be helpful if you wish to modify the project in any way and then upload the new version manually to Pages.
6. Select **Create pages project** to begin project creation. A new Pages project will be automatically created and your API schema will be automatically uploaded to the project along with other supporting static content.
7. Select **Deploy site**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **API Shield** \> **Settings**.
3. Under **Create a developer portal**, select **Create site**.
4. Upload an OpenAPI v3.0 schema file or choose to select an existing schema from API Shield.  
Note  
If you do not have a schema to upload or to select from a pre-existing schema, export your Endpoint Management schema. For best results, include the learned parameters.  
Only API schemas uploaded to Schema validation 2.0 are available when selecting existing schemas.
5. Select **Download project files** to save a local copy of the files that will be uploaded to Cloudflare Pages. Downloading the project files can be helpful if you wish to modify the project in any way and then upload the new version manually to Pages.
6. Select **Create pages project** to begin project creation. A new Pages project will be automatically created and your API schema will be automatically uploaded to the project along with other supporting static content.
7. Select **Deploy site**.

### Custom domains

To create a vanity domain instead of using the pages.dev domain, refer to the [Pages custom domain documentation](https://developers.cloudflare.com/pages/configuration/custom-domains/).

## Availability

Building developer portals is available to all API Shield subscribers. This feature uses Cloudflare Pages to host the resulting portal. Refer to [Pages](https://developers.cloudflare.com/pages/) for any limitations of your current subscription plan.

## Limitations

This feature currently uses the open source [Redoc ↗](https://github.com/Redocly/redoc) project from [Redocly ↗](https://redocly.com/). For custom theme and branding options, visit the [Redoc GitHub repository ↗](https://github.com/Redocly/redoc).

To modify the resulting page, download the project files before creating the Pages project. You can create a new Pages project with the modified files you have made to meet your branding guidelines.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/management-and-monitoring/","name":"Management and Monitoring"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/management-and-monitoring/developer-portal/","name":"Build developer portals"}}]}
```

---

---
title: Endpoint labeling service
description: Organize API endpoints and address vulnerabilities with managed and custom labels.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Endpoint labeling service

API Shield's labeling service will help you organize your endpoints and address vulnerabilities in your API. The labeling service comes with managed and user-defined labels.

Managed labels help you organize endpoints by use case. Managed labels will also automatically identify endpoints with informative or security risks, alerting you on endpoints that need attention.

User-defined labels can also be added to endpoints in API Shield by creating a label and adding it to an individual endpoint or multiple endpoints. User-defined labels will be useful for organizing your endpoints by owner, version, or type.

You can filter your endpoints based on the labels.

## Categories

### Managed labels

Use managed labels to identify endpoints by use case. Cloudflare may automatically apply these labels in a future release.

`cf-log-in`: Add this label to endpoints that accept user credentials. You may have multiple endpoints if you accept username, password, and multi-factor authentication (MFA) across multiple endpoints or requests.

`cf-sign-up`: Add this label to endpoints that are the final step in creating user accounts for your site or application.

`cf-content`: Add this label to endpoints that provide unique content, such as product details, user reviews, pricing, or other unique information.

`cf-purchase`: Add this label to endpoints that are the final step in purchasing goods or services online.

`cf-password-reset`: Add this label to endpoints that participate in the user password reset process. This includes initial password reset requests and final password reset submissions.

`cf-add-cart`: Add this label to endpoints that add items to a user's shopping cart or verify item availability.

`cf-add-payment`: Add this label to endpoints that accept credit card or bank account details where fraudsters may iterate through account numbers to guess valid combinations of payment information.

`cf-check-value`: Add this label to endpoints that check the balance of rewards points, in-game currency, or other stored value products that can be earned, transferred, and redeemed for cash or physical goods.

`cf-add-post`: Add this label to endpoints that post messages in a communication forum, or product or merchant reviews.

`cf-account-update`: Add this label to endpoints that participate in user account or profile updates.

`cf-llm`: Services that are (partially) powered by Large Language Model (LLM).

`cf-mcp`: Add this label to endpoints that implement the [Model Context Protocol (MCP)](https://developers.cloudflare.com/agents/model-context-protocol/) for AI tool and data access.

`cf-rss-feed`: Add this label to endpoints that expect traffic from RSS clients.

`cf-web-page`: Add this label to endpoints that serve HTML pages.

`cf-contains-ads`: Add this label to endpoints that serve web pages containing advertisements.

Note

[Bot Fight Mode](https://developers.cloudflare.com/bots/get-started/bot-fight-mode/) will not block requests to endpoints labeled as `cf-rss-feed`.

[Super Bot Fight Mode rules](https://developers.cloudflare.com/bots/get-started/super-bot-fight-mode/#ruleset-engine) will not match or challenge requests labeled as `cf-rss-feed`.

### Risk labels

Cloudflare automatically runs risk scans every 24 hours on your saved endpoints. API Shield applies these labels when a scan finds security risks on your endpoints. A corresponding Security Center Insight is also raised when risks are found.

`cf-risk-missing-auth`: Automatically added when all successful requests lack a session identifier. Refer to [Authentication Posture](https://developers.cloudflare.com/api-shield/security/authentication-posture/#process) for more information.

`cf-risk-mixed-auth`: Automatically added when some successful requests contain a session identifier and some successful requests lack a session identifier. Refer to [Authentication Posture](https://developers.cloudflare.com/api-shield/security/authentication-posture/#process) for more information.

`cf-risk-sensitive`: Automatically added to endpoints when HTTP responses match the WAF's [Sensitive Data Detection](https://developers.cloudflare.com/api-shield/management-and-monitoring/#sensitive-data-detection) ruleset.

`cf-risk-missing-schema`: Automatically added when a learned schema is available for an endpoint that has no active schema.

`cf-risk-error-anomaly`: Automatically added when an endpoint experiences a recent increase in response errors over the last 24 hours.

`cf-risk-latency-anomaly`: Automatically added when an endpoint experiences a recent increase in response latency over the last 24 hours.

`cf-risk-size-anomaly`: Automatically added when an endpoint experiences a spike in response body size over the last 24 hours.

`cf-risk-bola-enumeration`: Automatically added when an endpoint experiences successful responses with drastic differences in the number of unique elements requested by different user sessions.

`cf-risk-bola-pollution`: Automatically added when an endpoint experiences successful responses where parameters are found in multiple places in the request, as opposed to what is expected from the API's schema.

`cf-risk-zombie`: Automatically added when a saved endpoint has not received traffic in 32 days.

Note

Cloudflare will only add authentication labels to endpoints with successful response codes. Refer to the below table for more details.

#### Recommended action

How you address risks to your endpoints will depend on its label(s). The following steps provide you with general guidelines on how to take action on them.

1. Review risks to endpoints.  
View the endpoints labeled as risks and identify if they have been labeled for other risks.  
For example, endpoints labeled `cf-risk-sensitive` and `cf-risk-missing-auth` or `cf-risk-mixed-auth` may contain sensitive data that is available to unauthenticated users.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)  
Go to the details pages for endpoints labeled as `cf-risk-missing-auth` or `cf-risk-mixed-auth`, and check for recent changes in the authenticated traffic profile in the last 24 hours and seven days.
2. Review traffic to these labeled endpoints in Security Analytics.  
Check for unexpected traffic sources and note any irregular traffic patterns.  
Filtering  
Filtering by risk label includes all traffic to all endpoints labeled with that risk, not only the traffic that prompted Cloudflare to apply the label.  
[ Go to **Analytics** ](https://dash.cloudflare.com/?to=/:account/:zone/security/analytics)
3. Review your origin's authorization and authentication policies with your development team.  
Speak with your developers or application owners in your organization to understand whether or not all requests to these endpoints should be authenticated. Modify your application to consistently enforce the authentication requirement for all traffic accessing these endpoints.  
Refer to [Authentication Posture](https://developers.cloudflare.com/api-shield/security/authentication-posture/) for more information.

---

## Analytics

### GraphQL Analytics API

You can query the matched operation and managed labels for individual requests using the [GraphQL Analytics API](https://developers.cloudflare.com/analytics/graphql-api/). The `webAssetsOperationId` and `webAssetsLabelsManaged` fields are available in the `httpRequestsAdaptive` and `httpRequestsAdaptiveGroups` datasets. Use [introspection](https://developers.cloudflare.com/analytics/graphql-api/features/discovery/introspection/) to explore the full schema and available filter operators.

`webAssetsLabelsManaged` returns at most 10 labels per request.

#### Example: query requests by managed label

The following query returns the count of requests per operation ID and managed label set, filtered to requests where the matched operation carries the `cf-log-in` managed label.

```

query GetAdaptiveGroups($start: DateTime!, $end: DateTime!) {

  viewer {

    zones(filter: { zoneTag: $zoneTag }) {

      httpRequestsAdaptiveGroups(

        filter: {

          datetime_geq: $start

          datetime_leq: $end

          requestSource: "eyeball"

          webAssetsLabelsManaged_hasany: ["cf-log-in"]

        }

        limit: 25

        orderBy: [count_DESC]

      ) {

        count

        dimensions {

          webAssetsOperationId

          webAssetsLabelsManaged

        }

      }

    }

  }

}


```

Replace `cf-log-in` with any [managed label](#managed-labels) or [risk label](#risk-labels). You can also omit the `webAssetsLabelsManaged_hasany` filter and use `webAssetsOperationId` as the sole dimension to group traffic by matched operation regardless of label.

### Logpush

You can export per-request Web Assets data to your storage or SIEM system of choice using [Logpush](https://developers.cloudflare.com/logs/logpush/). The `WebAssetsOperationID` and `WebAssetsLabelsManaged` fields are available in the [HTTP requests dataset](https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/zone/http%5Frequests/#webassetslabelsmanaged).

---

## Create a label

* [  New dashboard ](#tab-panel-6539)
* [ Old dashboard ](#tab-panel-6540)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **API abuse**.
3. Under **Endpoint labels**, select **Manage labels**.
4. Name the label and add an optional label description.
5. Apply the label to your selected endpoints.
6. Select **Create label**.

Alternatively, you can create a user-defined label via **Security** \> **Web Assets**.

1. In the Cloudflare dashboard, go to the **Web Assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Endpoints** tab.
3. Choose the endpoint that you want to label.
4. Select **Edit endpoint labels**.
5. Under **User**, select **Create user label**.
6. Enter the label name.
7. Select **Create**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Settings** \> **Labels**.
3. Under **Security labels**, select **Create label**.
4. Name the label and add an optional label description.
5. Apply the label to your selected endpoints.
6. Select **Create label**.

Alternatively, you can create a user-defined label via Endpoint Management in API Shield:

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Settings** \> **Labels**.
3. Choose the endpoint that you want to label.
4. Select **Edit labels**.
5. Under **User**, select **Create user label**.
6. Enter the label name.
7. Select **Create**.

## Apply a label to an individual endpoint

* [  New dashboard ](#tab-panel-6541)
* [ Old dashboard ](#tab-panel-6542)

1. In the Cloudflare dashboard, go to the **Web assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. In the **Endpoints** tab, choose the endpoint that you want to label.
3. Select **Edit endpoint labels**.
4. Add the label(s) that you want to use for the endpoint from the list of managed and user-defined labels.
5. Select **Save labels**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **API Shield**.
3. In the **Endpoint Management** tab, choose the endpoint that you want to label.
4. Select **Edit labels**.
5. Add the label(s) that you want to use for the endpoint from the list of managed and user-defined labels.
6. Select **Save labels**.

## Bulk apply labels to multiple endpoints

* [  New dashboard ](#tab-panel-6537)
* [ Old dashboard ](#tab-panel-6538)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **API abuse**.
3. On **Endpoint labels**, select **Manage labels**.
4. On the existing label that you want to apply to multiple endpoints, select **Bulk apply**.
5. Choose the endpoints that you want to label by selecting its checkbox.
6. Select **Apply label**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Settings** \> **Labels**.
3. On the existing label that you want to apply to multiple endpoints, select **Bulk apply**.
4. Choose the endpoints that you want to label by selecting its checkbox.
5. Select **Save label**.

## Availability

Endpoint labeling is available to all customers.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/management-and-monitoring/","name":"Management and Monitoring"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/management-and-monitoring/endpoint-labels/","name":"Endpoint labeling service"}}]}
```

---

---
title: Endpoint Management
description: Save, organize, and monitor API endpoints in API Shield.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Endpoint Management

 Available on all plans 

Monitor the health of your API endpoints by saving, updating, and monitoring performance metrics using API Shield’s Endpoint Management.

**Add endpoints** allows customers to save endpoints directly from [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/) or manually by method, path, and host.

This will add the specified endpoints to your list of managed endpoints. You can view your list of saved endpoints in the **Endpoint Management** page.

Cloudflare will start collecting [performance data](https://developers.cloudflare.com/api-shield/management-and-monitoring/#endpoint-analysis) on your endpoint when you save an endpoint.

Note

When an endpoint is using [Cloudflare Workers](https://developers.cloudflare.com/workers/), the metrics data will not be populated.

## Access

* [  New dashboard ](#tab-panel-6553)
* [ Old dashboard ](#tab-panel-6554)

1. In the Cloudflare dashboard, go to the **Web Assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Endpoints** tab.
3. Select **Add endpoints**.
4. Add your endpoints [manually](#add-endpoints-manually), from [Schema validation](#add-endpoints-from-schema-validation), or from [API Discovery](#add-endpoints-from-api-discovery).

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/login), and select your account and domain.
2. Select **Security** \> **API Shield**.
3. Add your endpoints [manually](#add-endpoints-manually), from [Schema validation](#add-endpoints-from-schema-validation), or from [API Discovery](#add-endpoints-from-api-discovery).

### Add endpoints from API Discovery

There are two ways to add API endpoints from Discovery.

#### Add from the Endpoints tab

* [  New dashboard ](#tab-panel-6543)
* [ Old dashboard ](#tab-panel-6544)

1. From **Endpoints**, go to **Add endpoints** \> **Select from Discovery** tab.
2. Select the discovered endpoints you would like to add.
3. Select **Add endpoints**.

1. From **Endpoint Management**, select **Add endpoints** \> **Select from Discovery** tab.
2. Select the discovered endpoints you would like to add.
3. Select **Add endpoints**.

#### Add from the Discovery tab

* [  New dashboard ](#tab-panel-6545)
* [ Old dashboard ](#tab-panel-6546)

1. From **Web assets**, go to the **Discovery** tab.
2. Select the discovered endpoints you would like to add.
3. Select **Save selected endpoints**.

1. From Endpoint Management, select the **Discovery** tab.
2. Select the discovered endpoints you would like to add.
3. Select **Save selected endpoints**.

### Add endpoints from Schema validation

* [  New dashboard ](#tab-panel-6547)
* [ Old dashboard ](#tab-panel-6548)

1. From **Web assets**, go to the **Endpoints** tab.
2. Select **Add endpoints** \> **Upload Schema**.
3. Upload a schema file.
4. Select **Add schema and endpoints**.

1. Add a schema by [configuring Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/).
2. On **Review schema endpoints**, save new endpoints to endpoint management by checking the box.
3. Select **Save as draft** or **Save and Deploy**. Endpoints will be saved regardless of whether the schema is saved as a draft or published.

API Shield will look for duplicate endpoints that have the same host, method, and path. Duplicate endpoints will not be saved to endpoint management.

Note

If you deselect **Save new endpoints to endpoint management**, the endpoints will not be added.

### Add endpoints manually

* [  New dashboard ](#tab-panel-6549)
* [ Old dashboard ](#tab-panel-6550)

1. From **Web assets**, go to the **Endpoints** tab.
2. Select **Add endpoints** \> **Manually add**.
3. Choose the method from the dropdown menu and add the path and hostname for the endpoint.
4. Select **Add endpoints**.

1. From Endpoint Management, select **Add endpoints** \> **Manually add**.
2. Choose the method from the dropdown menu and add the path and hostname for the endpoint.
3. Select **Add endpoints**.

Note

By selecting multiple checkboxes, you can add several endpoints from Discovery at once instead of individually.

When adding an endpoint manually, you can specify variable fields in the path or host by enclosing them in braces, `/api/user/{var1}/details` or `{hostVar1}.example.com`.

Cloudflare supports hostname variables in the following formats:

```

{hostVar1}.example.com


foo.{hostVar1}.example.com


{hostVar2}.{hostVar1}.example.com


```

Hostname variables must comprise the entire domain field and must not be used with other text in the field.

The following format is not supported:

```

foo-{hostVar1}.example.com


```

For more information on how Cloudflare uses variables in API Shield, refer to the examples from [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/).

### Delete endpoints manually

You can delete endpoints one at a time or in bulk.

* [  New dashboard ](#tab-panel-6551)
* [ Old dashboard ](#tab-panel-6552)

1. From **Web assets**, go to the **Endpoints** tab.
2. Select the checkboxes for the endpoints that you want to delete.
3. Select **Delete endpoints**.

1. From Endpoint Management, select the checkboxes for the endpoints that you want to delete.
2. Select **Delete endpoints**.

Warning

When you delete an endpoint from Endpoint Management, Cloudflare immediately stops tracking all associated performance and analytics data. The endpoint's previous historical metrics are permanently removed and cannot be restored. If you later save this endpoint again, metric tracking will resume, starting from the point the endpoint is re-saved.

## Endpoint Analysis

For each saved endpoint, customers can view:

* **Request count**: The total number of requests to the endpoint over time.
* **Rate limiting recommendation**: per 10 minutes. This is guided by the request count.
* **Latency**: The average origin response time in milliseconds (ms). This metric shows how long it takes from the moment a visitor makes a request to the moment the visitor gets a response back from the origin.
* **Error rate** vs. overall traffic: grouped by 4xx, 5xx, and their sum.
* **Response size**: The average size of the response (in bytes) returned to the request.
* **Labels**: The current [labels](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/) assigned to the endpoint.
* **[Authentication status](https://developers.cloudflare.com/api-shield/security/authentication-posture/)**: The breakdown of which [session identifiers](https://developers.cloudflare.com/api-shield/get-started/#session-identifiers) were seen on successful requests to this endpoint.
* **Sequences**: The number of [Sequence Analytics](https://developers.cloudflare.com/api-shield/security/sequence-analytics/) sequences the endpoint was found in.

Note

Customers viewing analytics have the ability to toggle detailed metrics view between the last 24 hours and 7 days.

## Using the Cloudflare API

You can interact with Endpoint Management through the Cloudflare API. Refer to [Endpoint Management’s API documentation](https://developers.cloudflare.com/api/resources/api%5Fgateway/subresources/discovery/subresources/operations/methods/list/) for more information.

## Sensitive Data Detection

Sensitive data comprises various personally identifiable information and financial data. Cloudflare created this ruleset to address common data loss threats, and the WAF can search for this data in HTTP response bodies from your origin.

API Shield will alert users to the presence of sensitive data in the response body of API endpoints listed in Endpoint Management if the zone is also subscribed to the [Sensitive Data Detection managed ruleset](https://developers.cloudflare.com/waf/managed-rules/reference/sensitive-data-detection/).

Sensitive Data Detection is available to Enterprise customers on our Advanced application security plan.

Once Sensitive Data Detection is enabled for your zone, API Shield queries firewall events from the WAF for the last seven days and places a notification icon on the Endpoint Management table row if there are any matched sensitive responses for your endpoint.

API Shield displays the types of sensitive data found if you expand the Endpoint Management table row to view further details. Select **Explore Events** to view the matched events in Security Events.

After Sensitive Data Detection is enabled for your zone, you can [browse the Sensitive Data Detection ruleset ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/data/ruleset/e22d83c647c64a3eae91b71b499d988e/rules). The link will not work if Sensitive Data Detection is not enabled.

## Limitations

Certain performance metrics, such as latency, are not supported when a request is handled by a Cloudflare service in a way that prevents it from being passed directly to your origin server.

This limitation is specifically observed when:

* A Cloudflare Worker is running on the URL path.
* Other products built on top of Workers, such as [Waiting Room](https://developers.cloudflare.com/waiting-room/), are active on the application.

In these scenarios, the system is unable to accurately measure the origin response time, and the metric will not be populated in the dashboard.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/management-and-monitoring/","name":"Management and Monitoring"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/management-and-monitoring/endpoint-management/","name":"Endpoint Management"}}]}
```

---

---
title: Schema learning
description: Automatically learn API schema parameters from traffic and export in OpenAPI format.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Schema learning

Schema learning observes live API traffic to automatically discover the parameters, headers, and body formats your endpoints accept. For all endpoints saved to Endpoint Management, you can export the learned schema in OpenAPI `v3.0.0` format by hostname.

To protect your API with a learned schema, refer to [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/#add-validation-by-applying-a-learned-schema-to-an-entire-hostname).

## Export a schema

* [  New dashboard ](#tab-panel-6555)
* [ Old dashboard ](#tab-panel-6556)

1. In the Cloudflare dashboard, go to the **Web Assets** page.  
[ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Endpoints** tab.
3. Select **Export schema** and choose a hostname to export.
4. Select whether to include learned parameters and rate limit recommendations
5. Select **Export schema** and choose a location to save the file.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Select **Security** \> **API Shield** \> **Endpoint Management**.
3. Select **Export schema** and choose a hostname to export.
4. Select whether to include [learned parameters](https://developers.cloudflare.com/api-shield/management-and-monitoring/#learned-schemas-will-always-include) and [rate limit recommendations](https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/)
5. Select **Export schema** and choose a location to save the file.

Note

The schema is saved as a JSON file in OpenAPI `v3.0.0` format.

Learned schemas will always include:

* The listed hostname in the servers section
* All endpoints by host, method, and path

For endpoints that receive sufficient traffic, learned schemas will also include:

* Detected path variables and formats
* Detected query parameters and formats
* Detected `POST`, `PUT`, and `PATCH` body variable names and formats for `application/json` content types

Learned schemas can optionally include:

* API Shield's rate limit threshold recommendations

## Limitations

Endpoints must be added for at least 24 hours before schema learning begins. Schema learning is a continuous process that inspects the last 72 hours of traffic to an endpoint.

Schema learning only learns from requests with `2xx` response codes.

Schema learning works best with high volumes of traffic. You may see less confident learned schemas for endpoints with less than 10,000 requests in the last 72 hours.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/management-and-monitoring/","name":"Management and Monitoring"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/management-and-monitoring/endpoint-management/","name":"Endpoint Management"}},{"@type":"ListItem","position":5,"item":{"@id":"/api-shield/management-and-monitoring/endpoint-management/schema-learning/","name":"Schema learning"}}]}
```

---

---
title: Session identifiers
description: Configure session identifiers to track authenticated API traffic per user.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Session identifiers

While not strictly required, it is recommended that you configure your session identifiers when getting started with API Shield. When Cloudflare inspects your API traffic for individual sessions, we can offer more tools for visibility, management, and control.

If you are unsure of the session identifiers that your API uses, consult with your development team.

Session identifiers should uniquely identify API clients. A common session identifier for API traffic is the `Authorization` header. When a [JSON Web Token (JWT)](https://developers.cloudflare.com/api-shield/security/jwt-validation/) is used by the API for client authentication, its value may change over time. You can use a claim value inside the JWT such as `sub` or `email` as a session ID to uniquely identify the session over time.

If your API uses the `Authorization` header on more than 1% of successful requests to your zone, Cloudflare will automatically set it as the API Shield session identifier.

Note

You must have specific entitlements to configure session identifiers or cookies as a form of identifiers, such as an Enterprise subscription, for features such as [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/), [Sequence Mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/) or [rate limiting recommendations](https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/), and to see results in [Sequence Analytics](https://developers.cloudflare.com/api-shield/security/sequence-analytics/) and [Authentication Posture](https://developers.cloudflare.com/api-shield/security/authentication-posture/).

## To set up session identifiers

* [  New dashboard ](#tab-panel-6557)
* [ Old dashboard ](#tab-panel-6558)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **API abuse**.
3. On **Session identifiers**, select **Configure session identifiers**.
4. Select **Manage identifiers**.
5. Choose the type of session identifier (cookie, HTTP header, or JWT claim).  
Note  
The session identifier cookie must comply with RFC 6265\. Otherwise, it will be rejected.  
If you are using a JWT claim, choose the [Token Configuration](https://developers.cloudflare.com/api-shield/security/jwt-validation/api/#token-configurations) that will verify the JWT. Token Configurations are required to use JWT claims as session identifiers. Refer to [JWT Validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/) for more information.
6. Enter the name of the session identifier.
7. Select **Save**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/login), and select your account and domain.
2. Go to **Security** \> **API Shield**.
3. Select **Settings**.
4. On **Endpoint settings**, select **Manage identifiers**.
5. Choose the type of session identifier (cookie, HTTP header, or JWT claim).  
Note  
The session identifier cookie must comply with RFC 6265\. Otherwise, it will be rejected.  
If you are using a JWT claim, choose the [Token Configuration](https://developers.cloudflare.com/api-shield/security/jwt-validation/api/#token-configurations) that will verify the JWT. Token Configurations are required to use JWT claims as session identifiers. Refer to [JWT Validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/) for more information.
6. Enter the name of the session identifier.
7. Select **Save**.

After setting up session identifiers and allowing some time for Cloudflare to learn your traffic patterns, you can view your per endpoint and per session rate limiting recommendations, as well as enforce per endpoint and per session rate limits by creating new rules. Session identifiers will allow you to view API Discovery results from session ID-based discovery and session traffic patterns in Sequence Analytics.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/management-and-monitoring/","name":"Management and Monitoring"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/management-and-monitoring/session-identifiers/","name":"Session identifiers"}}]}
```

---

---
title: Classic Schema validation (deprecated)
description: Reference for the deprecated classic Schema validation feature in API Shield.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Classic Schema validation (deprecated)

Deprecation notice

Classic Schema validation has been deprecated.

Upload all new schemas to [Schema validation 2.0](https://developers.cloudflare.com/api-shield/security/schema-validation/).

Use the **API Shield** interface to configure [API Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), which validates requests according to the API schema you provide.

Before you can configure Schema validation for an API, you must obtain an API Schema file matching our [specifications](https://developers.cloudflare.com/api-shield/security/schema-validation/#specifications).

If you are in the Schema validation 2.0, you can make changes to your settings but you cannot add any new Classic Schema validation schemas.

Note

This feature is only available for customers on an Enterprise plan. Contact your Cloudflare Customer Success Manager to get access.

## Create an API Shield with Schema validation

To configure Schema validation in the Cloudflare dashboard:

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com) and select your account and domain.
2. Select **Security** \> **API Shield**.
3. Go to **Schema validation** and select **Add schema**.
4. Enter a descriptive name for your policy and optionally edit the expression to trigger Schema validation. For example, if your API is available at `http://api.example.com/v1`, include a check for the _Hostname_ field — equal to `api.example.com` — and a check for the _URI Path_ field using a regular expression — matching the regex `^/v1`.

Important

To validate the hostname, you must include the _Hostname_ field explicitly in the rule, even if the hostname value is in the schema file. Any hostname value present in the schema file will be ignored.

1. Select **Next**.
2. Upload your schema file.
3. Select **Save** to validate the content of the schema file and deploy the Schema validation rule. If you get a validation error, ensure that you are using one of the [supported file formats](https://developers.cloudflare.com/api-shield/security/schema-validation/#specifications) and that each endpoint and method pair has a unique operation ID.

After deploying your API Shield rule, Cloudflare displays a summary of all API endpoints organized by their protection level and actions that will occur for non-compliant and unprotected requests.

1. In the **Endpoint action** dropdown, select an action for every request that targets a protected endpoint and fails Schema validation.
2. In the **Fallthrough action** dropdown, select an action for every request that targets an unprotected endpoint.
3. Optionally, you can save the endpoints to Endpoint Management at the same time the Schema is saved by selecting **Save new endpoints to [endpoint management](https://developers.cloudflare.com/api-shield/management-and-monitoring/)**. Endpoints will be saved regardless of whether the Schema is saved as a draft or published live.
4. Select **Done**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/reference/classic-schema-validation/","name":"Classic Schema validation (deprecated)"}}]}
```

---

---
title: Terraform
description: Configure API Shield resources with Terraform, including endpoints and schemas.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Terraform

Get started with API Shield using Terraform from the examples below. For more information on how to use Terraform with Cloudflare, refer to the [Terraform documentation](https://developers.cloudflare.com/terraform/).

The following resources are available to configure through Terraform:

**Session identifiers**

* [api\_shield ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api%5Fshield) for configuring session identifiers in API Shield.

**Endpoint Management**

* [api\_shield\_operation ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api%5Fshield%5Foperation) for configuring endpoints in Endpoint Management.

**Schema validation**

* [cloudflare\_schema\_validation\_schemas ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/schema%5Fvalidation%5Fschemas) for configuring a schema in [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/).~~[api\_shield\_schema ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api%5Fshield%5Fschema)~~ has been deprecated and will be removed in a future version of the terraform provider.
* [cloudflare\_schema\_validation\_settings ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/schema%5Fvalidation%5Fsettings) for configuring zone-level Schema validation settings.~~[api\_shield\_schema\_validation\_settings ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api%5Fshield%5Fschema%5Fvalidation%5Fsettings)~~ has been deprecated and will be removed in a future version of the terraform provider.
* [cloudflare\_schema\_validation\_operation\_settings ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/schema%5Fvalidation%5Foperation%5Fsettings) for configuring operation-level Schema validation settings.~~[api\_shield\_operation\_schema\_validation\_settings ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api%5Fshield%5Foperation%5Fschema%5Fvalidation%5Fsettings)~~ has been deprecated and will be removed in a future version of the terraform provider.

**JWT Validation**

* [cloudflare\_token\_validation\_config ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/token%5Fvalidation%5Fconfig) for setting up JWT validation with specific keying material and token locations.
* [cloudflare\_token\_validation\_rules ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/token%5Fvalidation%5Frules) for setting up rules to action on the validation result.

## Manage API Shield session identifiers

Refer to the example configuration below to set up [session identifiers](https://developers.cloudflare.com/api-shield/get-started/#to-set-up-session-identifiers) on your zone.

Example configuration

```

resource "cloudflare_api_shield" "session_identifiers" {

  zone_id = var.zone_id

  auth_id_characteristics = [{

    name = "authorization"

    type = "header"

  }]

}


```

## Manage API Shield Endpoint Management

Refer to the example configuration below to [manage endpoints](https://developers.cloudflare.com/api-shield/management-and-monitoring/) on your zone.

Example configuration

```

resource "cloudflare_api_shield_operation" "get_image" {

  zone_id  = var.zone_id

  method   = "GET"

  host     = "example.com"

  endpoint = "/api/images/{var1}"

}


resource "cloudflare_api_shield_operation" "post_image" {

  zone_id  = var.zone_id

  method   = "POST"

  host     = "example.com"

  endpoint = "/api/images/{var1}"

}


```

## Manage Schema validation

Note

It is required to configure Endpoint Management if you want to set up Schema validation using Terraform.

Refer to the example configuration below to manage [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/api/) on your zone.

Example configuration

```

# Schema that should be used for Schema validation

resource "cloudflare_schema_validation_schemas" "example_schema" {

  zone_id            = var.zone_id

  kind               = "openapi_v3"

  name               = "example-schema.yaml"

  # In this example, we assume that the `example-schema.yaml` includes `get_image` and `post_image` operations from above

  source             = file("./schemas/example-schema.yaml")

  validation_enabled = true

}


# Block all requests that violate schema by default

resource "cloudflare_schema_validation_settings" "zone_level_settings" {

  zone_id                              = var.zone_id

  validation_default_mitigation_action = "block"

}


# For endpoint post_image - only log requests that violate schema

resource "cloudflare_schema_validation_operation_settings" "post_image_log_only" {

  zone_id           = var.zone_id

  operation_id      = cloudflare_api_shield_operation.post_image.id

  mitigation_action = "log"

}


```

## Validate JWTs

Refer to the example configuration below to perform [JWT Validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/) on your zone.

Example configuration

```

# Setting up JWT validation with specific keying material and location of the token

resource "cloudflare_token_validation_config" "example_es256_config" {

  zone_id       = var.zone_id

  token_type    = "JWT"

  title         = "ES256 Example"

  description   = "An example configuration that validates ES256 JWTs with `b0078548-c9bc-46e5-a678-06fb72443427` key ID in the authorization header"

  token_sources = ["http.request.headers[\"authorization\"][0]"]

  credentials   = {

    keys = [

      {

        alg = "ES256"

        kid = "b0078548-c9bc-46e5-a678-06fb72443427"

        kty = "EC"

        crv = "P-256"

        x   = "yl_BZSxUG5II7kJCMxDfWImiU6zkcJcBYaTgzV3Jgnk"

        y   = "0qAzLQe_YGEdotb54qWq00k74QdiTOiWnuw_YzuIqr0"

      }

    ]

  }

}


# Setting up JWT rules for all configured endpoints on `example.com` except for `get_image`

resource "cloudflare_token_validation_rules" "example_com" {

 zone_id      = var.zone_id

 title        = "Validate JWTs on example.com"

 description  = "This actions JWT validation results for requests to example.com except for the get_image endpoint"

 action       = "block"

 enabled      = true

 # Require that the JWT described through the example_es256_config is valid.

 # Reference the ID of the generated token config, this constructs: is_jwt_valid("<id>")

 # If the expression is >not true<, Cloudflare will perform the configured action on the request

 expression   = format("(is_jwt_valid(%q))", cloudflare_token_validation_config.example_es256_config.id)

 selector     = {

    # all current and future operations matching this include selector will perform the described action when the expression fails to match

    include = [

      {

        host          = ["example.com"]

      }

    ]

    exclude = [

      {

        # reference the ID of the get_image operation to exclude it

        operation_ids = ["${cloudflare_api_shield_operation.get_image.id}"]

      }

    ]

 }

}


# With JWT validation, we can also refine session identifiers to use claims from the JWT

resource "cloudflare_api_shield" "session_identifiers" {

  zone_id = var.zone_id

  auth_id_characteristics = [{

    # select the JWT's `sub` claim as an extremely stable session identifier

    # this is "<token_config_id:json_path>" format

    name = "${cloudflare_token_validation_config.example_es256_config.id}:$.sub"

    type = "jwt"

  }]

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/api-shield/","name":"API Shield"}},{"@type":"ListItem","position":3,"item":{"@id":"/api-shield/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/api-shield/reference/terraform/","name":"Terraform"}}]}
```

---

---
title: Cloudflare bot solutions
description: Identify and mitigate automated traffic to protect your domain from bad bots.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare bot solutions

Identify and mitigate automated traffic to protect your domain from bad bots.

 Available on all plans 

Bots — automated software that sends requests to your site — can scrape content, stuff stolen credentials into login forms, hoard inventory, and inflate server costs. Cloudflare's bot solutions detect this automated traffic and let you decide how to respond.

Cloudflare offers three bot-specific products: Bot Fight Mode, Super Bot Fight Mode, and Bot Management for Enterprise.

Note

Enterprise customers can preview this product as a [non-contract service](https://developers.cloudflare.com/billing/understand/preview-services/), which provides full access, free of metered usage fees, limits, and certain other restrictions.

## Which bot solution do I need?

If you need a simple toggle that challenges detected bots across your entire domain, use Bot Fight Mode (Free) or Super Bot Fight Mode (Pro, Business, Enterprise without Bot Management add-on). These products are included with your plan but do not allow you to write rules based on bot score or target specific endpoints. Super Bot Fight Mode adds configurable actions per bot category and supports WAF custom rule exceptions, but does not offer the granular per-request scoring of Bot Management.

If you need granular control — per-request bot scores, custom rules, per-endpoint handling, and detailed analytics — use Bot Management for Enterprise. This is recommended for ecommerce, banking, and security use cases. To enable Bot Management for Enterprise, contact your account team.

To see the differences in features and functionality, visit [Plans](https://developers.cloudflare.com/bots/plans/).

## Features

###  Bot Fight Mode 

Challenge detected bot traffic across your entire domain with a single toggle.

[ Use Bot Fight Mode ](https://developers.cloudflare.com/bots/get-started/bot-fight-mode/) 

###  Super Bot Fight Mode 

Identify traffic matching patterns of known bots, challenge or block bots, protect static resources, and view analytics to help you understand bot traffic using Super Bot Fight Mode.

[ Use Super Bot Fight Mode ](https://developers.cloudflare.com/bots/get-started/super-bot-fight-mode/) 

###  Bot Analytics 

Use Bot Analytics to dynamically examine bot traffic.

[ Use Bot Analytics ](https://developers.cloudflare.com/bots/bot-analytics/) 

###  Firewall variables 

Access several new variables within the Firewall expression builder.

[ Use Firewall variables ](https://developers.cloudflare.com/bots/reference/bot-management-variables/) 

## Related products

**[API Shield](https://developers.cloudflare.com/api-shield/)** 

Identify and address API vulnerabilities using API Shield.

**[DDoS Protection](https://developers.cloudflare.com/ddos-protection/)** 

Detect and mitigate Distributed Denial of Service (DDoS) attacks using Cloudflare's Autonomous Edge.

**[Turnstile](https://developers.cloudflare.com/turnstile/)** 

Use Cloudflare's smart CAPTCHA alternative to run less intrusive challenges.

**[WAF](https://developers.cloudflare.com/waf/)** 

Get automatic protection from vulnerabilities and the flexibility to create custom rules.

## More resources

[Plans](https://www.cloudflare.com/plans/#overview) 

Compare available Cloudflare plans

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}}]}
```

---

---
title: Plans
description: Compare bot protection features available on each Cloudflare plan.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Plans

To learn more about features and functionality, select a plan.

[ Free ](https://developers.cloudflare.com/bots/plans/free/) [ Pro ](https://developers.cloudflare.com/bots/plans/pro/) [ Business ](https://developers.cloudflare.com/bots/plans/biz-and-ent/) [ Bot Management for Enterprise ](https://developers.cloudflare.com/bots/plans/bm-subscription/) 

## How do I get started?

To get started, review our [setup guides](https://developers.cloudflare.com/bots/get-started/). If you have any questions, visit the [community ↗](https://community.cloudflare.com/) to engage with other Cloudflare users.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/plans/","name":"Plans"}}]}
```

---

---
title: Business
description: Bot protection features included in the Business and Enterprise plans.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Business

To learn more about features and functionality, select a plan.

[ Free ](https://developers.cloudflare.com/bots/plans/free/) [ Pro ](https://developers.cloudflare.com/bots/plans/pro/) [ Business ](https://developers.cloudflare.com/bots/plans/biz-and-ent/) [ Bot Management for Enterprise ](https://developers.cloudflare.com/bots/plans/bm-subscription/) 

| **Plan name**             | Super Bot Fight Mode                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Availability**          | All Business customers and Enterprise customers without Bot Management[1](#user-content-fn-1)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| **Type of bots detected** | Simple bots, headless browsers, and many sophisticated bots                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| **Actions**               | Customer chooses whether to allow, block, or challenge                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| **Analytics**             | Dedicated Bot Analytics tool, available in **Security Analytics**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| **Control**               | Applied to all traffic across a domain                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| **Additional features**   | [Block AI bots](https://developers.cloudflare.com/bots/additional-configurations/block-ai-bots/), [AI Labyrinth](https://developers.cloudflare.com/bots/additional-configurations/ai-labyrinth/), [Instruct AI bot traffic with robots.txt](https://developers.cloudflare.com/bots/additional-configurations/managed-robots-txt/), [Definitely and Likely automated bots](https://developers.cloudflare.com/bots/concepts/bot-score/#bot-groupings), [Verified bots](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/), [Static resource protection](https://developers.cloudflare.com/bots/additional-configurations/static-resources/), [Optimize for WordPress](https://developers.cloudflare.com/bots/troubleshooting/wordpress-loopback-issue/), [JavaScript Detections](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/javascript-detections/) |

## Bot settings versus custom rules

The following features are handled automatically in **Security Settings** and do not require custom rules:

| Feature                                         | Handled by bot settings | Requires custom rules                                                                     |
| ----------------------------------------------- | ----------------------- | ----------------------------------------------------------------------------------------- |
| Block or challenge definitely automated traffic | Yes                     | Only for path-specific or threshold-tuned rules                                           |
| Block or challenge likely automated traffic     | Not available on Pro    | Yes, with [Bot Management](https://developers.cloudflare.com/bots/plans/bm-subscription/) |
| Allow or block verified bots                    | Yes                     | No                                                                                        |
| Block AI crawlers                               | Yes                     | Only to target individual AI crawlers                                                     |
| Protect static resources                        | Yes                     | No                                                                                        |
| Optimize for WordPress                          | Yes                     | No                                                                                        |

For more details on when custom rules are needed, refer to [custom rules](https://developers.cloudflare.com/bots/additional-configurations/custom-rules/).

## How do I get started?

To get started, review our [setup guides](https://developers.cloudflare.com/bots/get-started/). If you have any questions, visit the [community ↗](https://community.cloudflare.com/) to engage with other Cloudflare users.

## Footnotes

1. When users purchase Bot Management for Enterprise, Cloudflare automatically replaces and disables other bot products to prevent overlap. [↩](#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":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/plans/","name":"Plans"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/plans/biz-and-ent/","name":"Business"}}]}
```

---

---
title: Enterprise Bot Management
description: Advanced bot detection and mitigation features in the Bot Management add-on.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Enterprise Bot Management

To learn more about features and functionality, select a plan.

[ Free ](https://developers.cloudflare.com/bots/plans/free/) [ Pro ](https://developers.cloudflare.com/bots/plans/pro/) [ Business ](https://developers.cloudflare.com/bots/plans/biz-and-ent/) [ Bot Management for Enterprise ](https://developers.cloudflare.com/bots/plans/bm-subscription/) 

| **Plan name**             | Bot Management for Enterprise                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Availability**          | Added to Enterprise plans by your account team                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| **Enablement**            | Quick onboarding with help from our Solutions Engineering team                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| **Type of bots detected** | Simple and sophisticated bots, headless browsers, and domain-specific anomalies                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| **Actions**               | Customer chooses from several options, including block and various challenges                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| **Analytics**             | Dedicated Bot Analytics tool, available in **Security Analytics**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| **Control**               | Ability to restrict by path, IP address, and more. Access to [bot score](https://developers.cloudflare.com/bots/concepts/bot-score/), [JA3/JA4 fingerprint](https://developers.cloudflare.com/bots/additional-configurations/ja3-ja4-fingerprint/), [bot tags](https://developers.cloudflare.com/bots/concepts/bot-tags/) fields, and [detection IDs](https://developers.cloudflare.com/bots/additional-configurations/detection-ids/).                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| **Additional features**   | [Block AI bots](https://developers.cloudflare.com/bots/additional-configurations/block-ai-bots/), [AI Labyrinth](https://developers.cloudflare.com/bots/additional-configurations/ai-labyrinth/), [Instruct AI bot traffic with robots.txt](https://developers.cloudflare.com/bots/additional-configurations/managed-robots-txt/), [Definitely and Likely automated bots](https://developers.cloudflare.com/bots/concepts/bot-score/#bot-groupings), [Verified bots](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/), [Static resource protection](https://developers.cloudflare.com/bots/additional-configurations/static-resources/), [Optimize for WordPress](https://developers.cloudflare.com/bots/troubleshooting/wordpress-loopback-issue/), [JavaScript Detections](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/javascript-detections/) |

Note

Zones that have [Enterprise Bot Management](https://developers.cloudflare.com/bots/get-started/bot-management/) enabled will not see Bot Fight Mode or Super Bot Fight Mode under **Security** \> **Bots**.

## Bot settings vs. custom rules

Bot Management customers have both bot settings (configured in **Security Settings**) and the ability to create custom rules using bot score fields. Start with the bot settings for baseline protection, then add custom rules only when you need additional control.

| Feature                                         | Handled by bot settings | When to use custom rules instead                                                                                                           |
| ----------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| Block or challenge definitely automated traffic | No                      | Path-specific rules, custom thresholds, or combining with other fields                                                                     |
| Block or challenge likely automated traffic     | No                      | Path-specific rules, custom thresholds, or combining with other fields                                                                     |
| Allow or block verified bots                    | No                      | Granular control by verified bot category                                                                                                  |
| Block AI crawlers                               | Yes                     | Target individual AI crawlers using detection IDs                                                                                          |
| Protect static resources                        | No                      | Exclude static resources from specific rules                                                                                               |
| Optimize for WordPress                          | No                      | No                                                                                                                                         |
| Forward bot data to origin                      | No                      | Use [Transform Rules](https://developers.cloudflare.com/rules/transform/) or [Snippets](https://developers.cloudflare.com/rules/snippets/) |
| Detection ID targeting                          | No                      | Use cf.bot\_management.detection\_ids in [custom rules](https://developers.cloudflare.com/waf/custom-rules/)                               |
| JA3/JA4 fingerprint rules                       | No                      | Use cf.bot\_management.ja3\_hash or cf.bot\_management.ja4 in [custom rules](https://developers.cloudflare.com/waf/custom-rules/)          |

For more details on when custom rules are needed, refer to [custom rules](https://developers.cloudflare.com/bots/additional-configurations/custom-rules/).

## How do I get started?

To get started, review our [setup guides](https://developers.cloudflare.com/bots/get-started/). If you have any questions, visit the [community ↗](https://community.cloudflare.com/) to engage with other Cloudflare users.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/plans/","name":"Plans"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/plans/bm-subscription/","name":"Enterprise Bot Management"}}]}
```

---

---
title: Free
description: Bot protection features included in the Cloudflare Free plan.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Free

To learn more about features and functionality, select a plan.

[ Free ](https://developers.cloudflare.com/bots/plans/free/) [ Pro ](https://developers.cloudflare.com/bots/plans/pro/) [ Business ](https://developers.cloudflare.com/bots/plans/biz-and-ent/) [ Bot Management for Enterprise ](https://developers.cloudflare.com/bots/plans/bm-subscription/) 

| **Plan name**             | Bot Fight Mode                                                                                                                                                                                                                                                                                                                    |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Availability**          | All Free customers                                                                                                                                                                                                                                                                                                                |
| **Type of bots detected** | Simple bots from cloud hosting providers and headless browsers                                                                                                                                                                                                                                                                    |
| **Actions**               | Cloudflare issues a computationally expensive challenge                                                                                                                                                                                                                                                                           |
| **Control**               | Applied to all traffic across a domain                                                                                                                                                                                                                                                                                            |
| **Additional features**   | [Block AI bots](https://developers.cloudflare.com/bots/additional-configurations/block-ai-bots/), [AI Labyrinth](https://developers.cloudflare.com/bots/additional-configurations/ai-labyrinth/), [Instruct AI bot traffic with robots.txt](https://developers.cloudflare.com/bots/additional-configurations/managed-robots-txt/) |

## How do I get started?

To get started, review our [setup guides](https://developers.cloudflare.com/bots/get-started/). If you have any questions, visit the [community ↗](https://community.cloudflare.com/) to engage with other Cloudflare users.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/plans/","name":"Plans"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/plans/free/","name":"Free"}}]}
```

---

---
title: Pro
description: Bot protection features included in the Cloudflare Pro plan.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Pro

To learn more about features and functionality, select a plan.

[ Free ](https://developers.cloudflare.com/bots/plans/free/) [ Pro ](https://developers.cloudflare.com/bots/plans/pro/) [ Business ](https://developers.cloudflare.com/bots/plans/biz-and-ent/) [ Bot Management for Enterprise ](https://developers.cloudflare.com/bots/plans/bm-subscription/) 

| **Plan name**             | Super Bot Fight Mode                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Availability**          | All Pro customers                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| **Type of bots detected** | Simple bots and headless browsers                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| **Actions**               | Customer chooses whether to allow, block, or challenge                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| **Analytics**             | Limited analytics available in a **Bot Report**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| **Control**               | Applied to all traffic across a domain                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| **Additional features**   | [Block AI bots](https://developers.cloudflare.com/bots/additional-configurations/block-ai-bots/), [AI Labyrinth](https://developers.cloudflare.com/bots/additional-configurations/ai-labyrinth/), [Instruct AI bot traffic with robots.txt](https://developers.cloudflare.com/bots/additional-configurations/managed-robots-txt/), [Definitely automated bots](https://developers.cloudflare.com/bots/concepts/bot-score/#bot-groupings), [Verified bots](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/), [Static resource protection](https://developers.cloudflare.com/bots/additional-configurations/static-resources/), [Optimize for WordPress](https://developers.cloudflare.com/bots/troubleshooting/wordpress-loopback-issue/), [JavaScript Detections](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/javascript-detections/) |

## Bot settings versus custom rules

The following features are handled automatically in **Security Settings** and do not require custom rules:

| Feature                                         | Handled by bot settings | Requires custom rules                                                                     |
| ----------------------------------------------- | ----------------------- | ----------------------------------------------------------------------------------------- |
| Block or challenge definitely automated traffic | Yes                     | Only for path-specific or threshold-tuned rules                                           |
| Block or challenge likely automated traffic     | Not available on Pro    | Yes, with [Bot Management](https://developers.cloudflare.com/bots/plans/bm-subscription/) |
| Allow or block verified bots                    | Yes                     | No                                                                                        |
| Block AI crawlers                               | Yes                     | Only to target individual AI crawlers                                                     |
| Protect static resources                        | Yes                     | No                                                                                        |
| Optimize for WordPress                          | Yes                     | No                                                                                        |

For more details on when custom rules are needed, refer to [custom rules](https://developers.cloudflare.com/bots/additional-configurations/custom-rules/).

## How do I get started?

To get started, review our [setup guides](https://developers.cloudflare.com/bots/get-started/). If you have any questions, visit the [community ↗](https://community.cloudflare.com/) to engage with other Cloudflare users.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/plans/","name":"Plans"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/plans/pro/","name":"Pro"}}]}
```

---

---
title: Bot Analytics
description: Use Bot Analytics to examine bot traffic patterns on your domain.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Bot Analytics

## Business and Enterprise

Business and Enterprise customers without Bot Management can use **Bot Analytics** to dynamically examine bot traffic. These dashboards offer less functionality than Bot Management for Enterprise but still help you understand bot traffic on your domain.

### Access

You can access Bot Analytics by going to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/login), and selecting your account and domain.

Old dashboard: **Security** \> **Bots**.

New dashboard: **Security** \> **Analytics** \> **Bot analysis**.

![View Bot Analytics in the Cloudflare dashboard. For more details, keep reading.](https://developers.cloudflare.com/_astro/bot-analytics-dashboard-biz.RDfO3DgS_Z1sosFo.webp) 

### Features

For a full tour of Bot Analytics, see [our blog post ↗](https://blog.cloudflare.com/introducing-bot-analytics/). At a high level, the tool includes:

* **Requests by traffic type**: View your total domain traffic segmented vertically by traffic type. Keep an eye on _automated_ and _likely automated_ traffic.
* **Requests by detection source**: Identify the most common detection engines used to score your traffic. Hover over a tooltip to learn more about each engine.
* **Top requests by attribute**: View more detailed information on specific IP addresses and other characteristics.

Bot Analytics shows up to 72 hours of data at a time and can display data up to 30 days old. Bot Analytics displays data in real time in most cases.

Cloudflare uses adaptive bitrate technology to show sampled data — most customers will see a 1-10% sample depending on how much information they are trying to view. Tooltips on the page will display the current sample rate.

### Common uses

Business and Enterprise customers without Bot Management can use Bot Analytics to:

* Understand bot traffic
* Study recent attacks to find trends and detailed information
* Learn more about Cloudflare’s detection engines with real data

For more details and granular control over bot traffic, consider upgrading to [Bot Management for Enterprise](https://developers.cloudflare.com/bots/bot-analytics/#enterprise-bot-management).

## Enterprise Bot Management

Enterprise customers with Bot Management can use **Bot Analytics** to dynamically examine bot traffic.

### Access

You can access Bot Analytics by going to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/login), and selecting your account and domain.

Old dashboard: **Security** \> **Bots**.

New dashboard: **Security** \> **Analytics** \> **Bot analysis**.

![View Bot Analytics in the Cloudflare dashboard. For more details, keep reading.](https://developers.cloudflare.com/_astro/bot-analytics-dashboard-ent.DA4XLihG_Zb6GXB.webp) 

### Features

For a full tour of Bot Analytics, see [our blog post ↗](https://blog.cloudflare.com/introducing-bot-analytics/). At a high level, the tool includes:

* **Requests by bot score**: View your total domain traffic and segment it vertically by traffic type. Keep an eye on _automated_ and _likely automated_ traffic.
* **Bot score distribution**: View the number of requests assigned a bot score 1 through 99.
* **Bot score source**: Identify the most common detection engines used to score your traffic. Hover over a tooltip to learn more about each engine.
* **Top requests by attribute**: View more detailed information on specific IP addresses and other characteristics.

Bot Analytics shows up to one week of data at a time and can display data up to 30 days old. Bot Analytics displays data in real time in most cases.

Cloudflare uses adaptive bitrate technology to show sampled data — most customers will see a 1-10% sample depending on how much information they are trying to view. Tooltips on the page will display the current sample rate.

### Common uses

Bot Management customers can use Bot Analytics to:

* Understand traffic during [your onboarding phase](https://developers.cloudflare.com/bots/get-started/bot-management/).
* Tune WAF custom rules to be effective but not overly aggressive.
* Study recent attacks to find trends and detailed information.
* Learn more about Cloudflare’s detection engines with real data.

### API

Data from Bot Analytics is also available via the GraphQL API. You can access bot scores, bot sources, [bot tags](https://developers.cloudflare.com/bots/concepts/bot-tags/), and bot _decisions_ (_automated_, _likely automated_, etc.), and more.

Read the [GraphQL Analytics API documentation](https://developers.cloudflare.com/analytics/graphql-api/) for more information about GraphQL and basic querying.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/bot-analytics/","name":"Bot Analytics"}}]}
```

---

---
title: Account Abuse Protection (Early Access)
description: Detect and block automated abuse on login and registration endpoints.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Account Abuse Protection (Early Access)

Identify and mitigate attacks on your customer and user accounts.

Account abuse — bulk account creation and account takeover attacks — can cause financial losses and erode user trust. Fraud detection allows you to detect and mitigate these attacks among your traffic. You can use fraud signals to [update or create new rules](https://developers.cloudflare.com/waf/custom-rules/) for suspicious account activity, or pass signals to your origin to integrate into authentication and authorization systems.

## Availability

Account Abuse Protection is available in Early Access for any [Bot Management Enterprise](https://developers.cloudflare.com/bots/get-started/bot-management) customer. You can use these features at no additional cost for a limited period until they are generally available.

Contact your Cloudflare account team to request access.

---

## Concepts

### User ID

User ID is a cryptographically hashed, per-zone identifier that customers can use in [Security Analytics](https://developers.cloudflare.com/waf/analytics/security-analytics/), [Security Rules](https://developers.cloudflare.com/waf/custom-rules/), and [Managed Transforms](https://developers.cloudflare.com/rules/transform/managed-transforms/reference/). Hashed User IDs are created by encrypting the primary credentials your users provide, converting them into opaque identifiers unique to your zone. This allows traffic analysis while protecting user privacy. With access to hashed User ID, website owners can:

* Review which users have the most activity on your website.
* Find the details on a specific user's characteristics and activity patterns.
* Mitigate traffic based on the user, such as blocking a user with historically suspicious activity.
* Combine fields to see when accounts are being targeted with leaked credentials.
* Manage network patterns or signals associated with specific users.

Data privacy

User profiling was created with privacy in mind. Its design and engineering align with our privacy and compliance programs and contain technical controls that protect the privacy of users. Hashed User IDs are created by encrypting the primary credentials your users use to access your applications.

Other Cloudflare customers cannot access your user profiles. They are unique to your zone.

User ID is an opt-in feature that can be enabled in Security Settings.

To enable, edit, or disable the setting:

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **Fraud**.
3. Go to **User ID**.
4. Turn **User ID** on or off.

### Ephemeral IDs

Customers using Cloudflare [Turnstile](https://developers.cloudflare.com/turnstile/) can utilize ephemeral IDs for Fraud detection.

Refer to [Fraud detection with ephemeral IDs](https://developers.cloudflare.com/turnstile/tutorials/fraud-detection-with-ephemeral-ids/) for more information.

### Account takeover detections

Cloudflare Bot Management includes dedicated detection IDs for account takeover attacks.

Refer to [Account takeover detections](https://developers.cloudflare.com/bots/additional-configurations/detection-ids/account-takeover-detections/) for more information.

Note

Account takeover (ATO) detections are not available for accounts using the [Data Localization Suite](https://developers.cloudflare.com/data-localization/) with [Regional Services](https://developers.cloudflare.com/data-localization/regional-services/) in the EU region. ATO detections rely on zone logs to identify suspicious activity, and Cloudflare does not ingest logs for these accounts to comply with General Data Protection (GDPR).

---

## Get started

### Prerequisites

Fraud detection requires the following configurations and settings to be enabled to properly identify suspicious behavior.

#### Security Settings

* User ID: Cloudflare encrypts or hashes your user IDs to better understand typical user traffic patterns across your applications. Enabling Cloudflare to create hashed user ID mappings to your users will allow you to receive account takeover and bulk account creation detections.

#### Eligible traffic

Cloudflare automatically identifies certain login and sign up traffic on your applications and runs these detections without any additional configurations.

* Sign-ups: Cloudflare automatically monitors traffic on endpoints that match common sign up endpoints.
* Login: Cloudflare automatically monitors traffic on endpoints that match common login endpoints.

Verify that your endpoints are properly labeled to ensure Cloudflare can detect and monitor them correctly.

Login or sign up endpoints

Not all login or sign up endpoints are automatically detected.

Cloudflare evaluates and automatically detects your website or application's login or sign up endpoint, but non-traditional login or sign up endpoints may not be recognized.

For example, if you have a non-traditional login endpoint, you should label it with `cf-log-in` using the [endpoint labeling service](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/). Once you have applied the `cf-log-in` label, Cloudflare will use the labeled endpoint for account takeover detection decisions.

Enhanced with leaked credential detections

Cloudflare also recommends enabling [Leaked credentials detection](https://developers.cloudflare.com/waf/detections/leaked-credentials/) to help identify compromised credentials across your users.

---

### Detections

Fraud detections focus on account abuse attacks such as account takeover, bulk account creation, and credential quality. These detections run on all eligible traffic and can be used across [Cloudflare Rules](https://developers.cloudflare.com/rules/) to log, challenge, and/or block requests to your sign up and login endpoints.

#### Account creation

Disposable Email Checks detect when users sign up with throwaway email addresses commonly used for promotion abuse and fake account creation. These disposable email services allow attackers to create thousands of unique accounts without maintaining real infrastructure.

You can use the following binary field as you build rules to enforce security preferences, choosing to block all disposable emails outright, or issue a [challenge](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/) to anyone attempting to create an account with a disposable email.

#### Suspicious emails

Cloudflare analyzes the components of an email used during sign up to help identify suspicious patterns. Refer to [prerequisites](#prerequisites) to ensure your traffic is eligible for detections.

Cloudflare does not store email addresses during this analysis. All detections processed without any storage or caching.

| Detection tag                         | Description                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cf.fraud\_detection.disposable\_email | Identifies emails with domains that are commonly found in lists of temporary or disposable email services.                                                                                                                                                                                                                                                                  |
| cf.fraud.email\_risk                  | Analyzes the randomness (entropy) of characters in an email username and top level domain. For example, a8xk2m9p@example.com has high entropy (very random characters), while john.smith@example.com has low entropy (recognizable pattern). High risk emails indicate high entropy, while medium and low risk emails indicate less randomness in the string of characters. |

---

### Mitigations

The following Fraud detection fields can be used in Security Rules to help identify and mitigate suspicious traffic.

#### Security Rules

The following fields can be used in new and existing Security Rules.

| Field                                  | Description                                                                                        | Values                                                                                                                                                                                                                                    |
| -------------------------------------- | -------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cf.fraud\_detection.disposable\_domain | Flags whether a domain for a given email is included in a known list of temporary email providers. | True or False                                                                                                                                                                                                                             |
| cf.fraud.email\_risk                   | Measures risk of email based on randomness of characters in the username and domain.               | Low represents low risk due to reduced randomness and simple emails. Medium represents medium risk based on larger strings with slightly more randomness. High represents high risk based on larger and random character strings. Unknown |

#### Other rules

You can use Fraud detection data in Request Header [Transform Rules](https://developers.cloudflare.com/rules/transform/managed-transforms/) to pass information down to the origin.

#### LogPush

You can add Fraud detection fields to existing or new [LogPush](https://developers.cloudflare.com/logs/logpush/) jobs.

---

## Analytics

You can find Fraud data and detections in Security Analytics, where you can see top User IDs.

[ Go to **Analytics** ](https://dash.cloudflare.com/?to=/:account/:zone/security/analytics) 

Fraud fields can be used as filters to identify suspicious patterns in your traffic.

The hashed User ID field within Security Analytics also provides Fraud customers with data that can help review detections and patterns per individual users rather than requests. You can review user level aggregations for IPs and IP counts, event types (login or sign up), locations, devices, and browsers.

A user level profile also provides a quick way to review the latest events associated with a user so that you can identify any anomalies and create a custom rule to log, block, or challenge that user.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/account-abuse-protection/","name":"Account Abuse Protection (Early Access)"}}]}
```

---

---
title: Glossary
description: Definitions for terms used across Cloudflare bot solutions documentation.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Glossary

Review the definitions for terms used across Cloudflare's Bots documentation.

| Term                       | Definition                                                                                                                                                                   |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| bot                        | A software application programmed to do tasks that can be used for good (chatbots, search engine crawlers) or for evil (inventory hoarding, credential stuffing).            |
| bot score                  | A score from 1 to 99 that indicates how likely that request came from a bot, in which 1 to 29 is likely automated and 30 to 99 is likely human.                              |
| bot tags                   | Additional information about a bot request, such as why Cloudflare has given it a bot score and whether the request came from a verified bot or a category of verified bots. |
| Challenge solve rate (CSR) | The percentage of issued challenges that were solved.                                                                                                                        |
| detection ID               | Static rules that are used to detect predictable bot behavior with no overlap with human traffic.                                                                            |
| JA3 fingerprint            | JA3 and JA4 fingerprints profile specific SSL/TLS clients across different destination IPs, Ports, and X509 certificates.                                                    |
| verified bot               | Bots that are transparent about who they are and what they do.                                                                                                               |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/glossary/","name":"Glossary"}}]}
```

---

---
title: Changelog
description: Track the latest updates and changes to Cloudflare bot solutions.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Changelog

[ Subscribe to RSS ](https://developers.cloudflare.com/bots/changelog/index.xml)

## 2025-07-02

**Managed robots.txt will prepend existing files**

Cloudflare will prepend our managed `robots.txt` before your existing `robots.txt`, combining both into a single response.

## 2025-06-26

**Web Bot Auth is now available for bot verification**

Web Bot Auth is an authentication method that leverages cryptographic signatures in HTTP messages to verify that a request comes from an automated bot. This provides a more robust way of verifying bots.

## 2025-05-14

**Anomaly detection events now receive a bot score of 2**

Events detected by the [anomaly detection engine](https://developers.cloudflare.com/bots/concepts/bot-detection-engines/#anomaly-detection-enterprise) are now given a bot score of 2.

## 2025-05-08

**Machine Learning model v9 is now the default model**

[Machine Learning model v9](https://developers.cloudflare.com/bots/reference/machine-learning-models/#model-versions-and-release-notes) is now the default model for all new zones and existing zones set to use the latest machine learning model.

## 2025-04-28

**Managed robots.txt is now available**

Direct AI crawlers on what they can and cannot scrape from your website or application by [implementing a robots.txt file](https://developers.cloudflare.com/bots/additional-configurations/managed-robots-txt/) to your domain.

## 2025-04-24

**Bot Detection Alerts are now available**

You can now create a [Bot Detection Alert](https://developers.cloudflare.com/bots/reference/alerts/) to notify you when Cloudflare detects a spike in Bot traffic on your website.

## 2024-08-19

**AI bots is now a managed rule**

[AI bots protection](https://developers.cloudflare.com/bots/concepts/bot/#ai-bots) has been upgraded from a custom rule to a managed rule.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/changelog/","name":"Changelog"}}]}
```

---

---
title: AI Labyrinth
description: Trap unauthorized AI crawlers with invisible honeypot links to waste their resources.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# AI Labyrinth

The AI Labyrinth adds invisible links on your webpage with specific `Nofollow` tags to block AI crawlers that do not adhere to the recommended guidelines and crawl without permission. AI crawlers that scrape your website content without permission will be stuck in a maze of never-ending links, and their details are recorded and used by all Cloudflare customers who choose to block [AI bots](https://developers.cloudflare.com/bots/concepts/bot/#ai-bots).

These links do not impact your search engine optimization (SEO) or your website's appearance, and are only seen by bots. AI bots that respect no-crawl instructions will safely ignore this honeypot.

To enable AI Labyrinth:

* [  New dashboard ](#tab-panel-6674)
* [ Old dashboard ](#tab-panel-6675)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **Bot traffic**.
3. Go to **AI Labyrinth**.
4. Turn **AI Labyrinth** on.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Bots**.
3. Select **Configure Bot Fight Mode**.
4. Enable **AI Labyrinth**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/additional-configurations/","name":"Additional configurations"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/additional-configurations/ai-labyrinth/","name":"AI Labyrinth"}}]}
```

---

---
title: Block AI Bots
description: Block AI crawlers and scrapers from accessing your website content.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Block AI Bots

Block AI bots availability

The **Block AI bots** feature is only available in the new [application security dashboard](https://developers.cloudflare.com/security/).

You can choose to block AI bots by activating **Block AI bots**. Activating this setting will block [verified bots](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/) that are classified as AI crawlers, as well as a number of unverified bots that behave similarly.

To block [AI bots](https://developers.cloudflare.com/bots/concepts/bot/#ai-bots):

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **Bot traffic**.
3. Go to **Block AI bots**.
4. Under **Configurations**, select the edit icon. Choose from:  
   * **Only block on hostnames with ads**: Use this option if you wish to block AI bots only on portions of your site that show ads. Cloudflare automatically detects whether ads are present on a subdomain, and only block on hostnames that contain those ad units.  
   * **Block on all pages**: Use this option if you wish to block AI bots on all your pages.  
   * **Do not block (off)**: Use this option if you wish to allow AI bots on all your pages.
5. Select **Save** to save your configuration.

To block individual AI crawlers (rather than blocking all crawlers), use [AI Crawl Control](https://developers.cloudflare.com/ai-crawl-control/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/additional-configurations/","name":"Additional configurations"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/additional-configurations/block-ai-bots/","name":"Block AI Bots"}}]}
```

---

---
title: Custom rules
description: Understand when to use the built-in bot protection settings in Security Settings versus creating WAF custom rules for bot management.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Custom rules

Bot protection on Cloudflare works through two complementary mechanisms: built-in settings configured through toggles in **Security Settings**, and [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/) that you write using [bot management fields](https://developers.cloudflare.com/bots/reference/bot-management-variables/). Understanding when to use each approach helps you avoid creating duplicate rules and simplifies your security configuration.

The following features are configured through toggles and dropdowns in [Security Settings](https://developers.cloudflare.com/security/settings/). They do not require you to write any rule expressions.

| Feature                                                                                                                 | What it does                                                                                                     | Availability                  |
| ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ----------------------------- |
| [Block AI bots](https://developers.cloudflare.com/bots/additional-configurations/block-ai-bots/)                        | Blocks AI crawlers (GPTBot, ClaudeBot, Bytespider, and others) using an auto-updating managed rule               | All plans                     |
| [AI Labyrinth](https://developers.cloudflare.com/bots/additional-configurations/ai-labyrinth/)                          | Feeds non-compliant AI crawlers into a maze of generated content                                                 | All plans                     |
| [Managed robots.txt](https://developers.cloudflare.com/bots/additional-configurations/managed-robots-txt/)              | Prepends AI crawler disallow directives to your robots.txt                                                       | All plans                     |
| Super Bot Fight Mode > **Definitely automated**                                                                         | Blocks or challenges traffic with a [bot score](https://developers.cloudflare.com/bots/concepts/bot-score/) of 1 | Pro, Business, Enterprise     |
| Super Bot Fight Mode > **Likely automated**                                                                             | Blocks or challenges traffic with a bot score of 2-29                                                            | Business, Enterprise          |
| [Verified bots](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/)                                     | Managed category of high-trust bots (Googlebot, Bingbot, and others)                                             | Pro, Business, Enterprise     |
| [Static resource protection](https://developers.cloudflare.com/bots/additional-configurations/static-resources/)        | Extends bot actions to cover static file types                                                                   | Pro, Business, Enterprise     |
| [Optimize for WordPress](https://developers.cloudflare.com/bots/troubleshooting/wordpress-loopback-issue/)              | Allows WordPress loopback requests through bot protection                                                        | Pro, Business, Enterprise     |
| [JavaScript detections](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/javascript-detections/) | Injects a lightweight script to identify clients that cannot execute JavaScript                                  | All plans (automatic on Free) |

Bot settings update automatically as Cloudflare identifies new bot signatures and AI crawlers, while custom rules require manual updates. They do not count toward your [custom rule limits](https://developers.cloudflare.com/waf/custom-rules/#availability), and apply uniformly across your domain without the risk of expression errors.

## Custom rules use cases

Custom rules are valuable when you need capabilities that built-in settings do not offer. The following scenarios require [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/) with [bot management fields](https://developers.cloudflare.com/bots/reference/bot-management-variables/). Bot management fields are available to customers with a [Bot Management](https://developers.cloudflare.com/bots/get-started/bot-management/) subscription.

### Path-specific protection

Since Bot settings apply to all traffic across your domain, you may need an alternative approach to bot handling for different paths using custom rules — for example, stricter protection on `/login/` than on `/public/`.

#### Example

Block likely automated traffic only on your login endpoint:

```

(cf.bot_management.score lt 30 and not cf.bot_management.verified_bot and http.request.uri.path eq "/login")


```

### Custom score thresholds

The **Definitely automated** and **Likely automated** settings in Super Bot Fight Mode use fixed bot score groupings (1 and 2-29). If you need a different threshold, for example, challenging all traffic with a score below 20, you need a custom rule.

### Conditional logic

If you need to combine bot score with other request fields, such as country, ASN, URI path, JA3/JA4 fingerprint, or user agent, you need custom rules. Bot settings do not support compound conditions.

#### Example

Challenge likely automated traffic only from specific ASNs:

```

(cf.bot_management.score lt 30 and not cf.bot_management.verified_bot and ip.src.asnum in {64496 65536})


```

### Custom actions

Bot settings offer **Block**, **Managed Challenge**, and **Allow** as actions.

If you need other actions, such as **Log** (for testing rules before enforcement), **Interactive Challenge**, or **Skip** (to bypass other rules), you need custom rules.

### Detection ID targeting

To act on specific bot heuristic detections, such as [account takeover](https://developers.cloudflare.com/bots/additional-configurations/detection-ids/account-takeover-detections/) or [scraping](https://developers.cloudflare.com/bots/additional-configurations/detection-ids/scraping-detections/) patterns, you need custom rules using the `cf.bot_management.detection_ids` field. Bot settings do not expose individual detection IDs.

### Forwarding bot data to origin

To send bot scores, verified bot status, or JA3/JA4 fingerprints to your origin server, use [Transform Rules](https://developers.cloudflare.com/rules/transform/) (including [Managed Transforms](https://developers.cloudflare.com/rules/transform/managed-transforms/)) or [Snippets](https://developers.cloudflare.com/rules/snippets/). These are not part of the built-in bot settings.

## Execution order

Custom rules execute before Super Bot Fight Mode managed rules. If a custom rule takes a terminating action (such as _Block_ or _Managed Challenge_), the request does not reach bot settings.

Refer to [Security features interoperability](https://developers.cloudflare.com/waf/feature-interoperability/) for more information.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/additional-configurations/","name":"Additional configurations"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/additional-configurations/custom-rules/","name":"Custom rules"}}]}
```

---

---
title: Detection IDs
description: Static rules that identify predictable bot behavior and configurable heuristics.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Detection IDs

Detection IDs are static rules that detect predictable bot behavior with no overlap with human traffic. Each ID maps to a specific [detection method](https://developers.cloudflare.com/bots/concepts/bot-detection-engines/) such as heuristics, verified bot detections, or anomaly detections. For example, a detection ID can identify when a client sends headers in a different order than what its claimed browser would use.

If you are having an issue with one of our heuristics, detection IDs allow you to decide which heuristics to enforce on your zones using customer configurable heuristics. You can choose unique actions for different bots, detected through Cloudflare’s heuristics engine. You can block, allow, or serve alternate content to specific bots to meet the unique needs of your site’s traffic.

Note

A request can trigger multiple detection IDs.

You can use `cf.bot_management.detection_ids` fields in tools such as:

* [Custom rules](https://developers.cloudflare.com/waf/custom-rules/)
* [Advanced Rate Limiting](https://developers.cloudflare.com/waf/rate-limiting-rules/)
* [Transform Rules](https://developers.cloudflare.com/rules/transform/)
* [Workers](https://developers.cloudflare.com/workers/) (as `request.cf.botManagement.detectionIds`)

Bot Detection IDs and tags are also available in [Bot Analytics](https://developers.cloudflare.com/bots/bot-analytics/) and [Security Analytics](https://developers.cloudflare.com/waf/analytics/security-analytics/).

Beta detections

Cloudflare may occasionally try beta detections as we continuously improve our detections.

It is possible, but uncommon, for you to have beta detection IDs on the Cloudflare dashboard that are not actively collecting data on your zone.

---

## Detection tags

Detection tags refer to the category associated with the detection ID at the time that Cloudflare has fingerprinted a bot. For example, if a detection tag is `go`, this means that Cloudflare has observed traffic from that detection ID from a Go programming language bot.

Note

Detection tags are available in Security Analytics, but not in the Security Events.

---

## Create or edit an expression

* [  New dashboard ](#tab-panel-6676)
* [ Old dashboard ](#tab-panel-6677)

1. In the Cloudflare dashboard, go to the **Security Analytics** page.  
[ Go to **Analytics** ](https://dash.cloudflare.com/?to=/:account/:zone/security/analytics)
2. Apply filters and select **Create custom security rule** to create a custom rule based on your filters.  
Alternatively, if you have already created a custom rule, you can go to the existing rule in **Security rules** and edit the expression based on your filters.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
3. Use the `cf.bot_management.detection_ids` field in the rule expression.
4. Select **Deploy**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Bots**, apply filters and select **Create custom rule** to create a [custom rule](https://developers.cloudflare.com/waf/custom-rules/create-dashboard/) based on those filters. Alternatively, if you already created a custom rule, go to **Security** \> **WAF** \> **Custom rules** and edit the expression of an existing custom rule.
3. Use the `cf.bot_management.detection_ids` field in the rule expression.
4. Select **Save**.

---

## Use cases

### Block requests that match a specific detection ID

JavaScript

```

any(cf.bot_management.detection_ids[*] eq 3355446)

and not cf.bot_management.verified_bot

and http.request.uri.path eq "/login"

and http.request.method eq "POST"


```

### Run Bot Management without specific detection IDs

JavaScript

```

cf.bot_management.score lt 30

and not cf.bot_management.verified_bot

and http.request.uri.path eq "/login"

and http.request.method eq "POST"

and not any(cf.bot_management.detection_ids[*] in {3355446 12577893})


```

---

## Bot Detection IDs via Logpush

You can create or edit existing Logpush jobs to include the new Bot Detection IDs field which will provide an array of IDs for each request that has heuristics match on it. The `BotDetectionIDs` field is available as part of the HTTP Requests dataset and you can add it to new or existing jobs via the Logpush API or on the Cloudflare dashboard. This is the primary method to discover Detection IDs.

* [ Dashboard ](#tab-panel-6678)
* [ API ](#tab-panel-6679)

1. In the Cloudflare dashboard, go to the **Logpush** page.  
[ Go to **Logpush** ](https://dash.cloudflare.com/?to=/:account/logs)
2. Select **Create a Logpush Job**.
3. Select and enter the destination information.
4. Select **HTTP Requests** as the dataset.
5. Select **BotDetectionIDs** under the General data field category.
6. Prove the ownership.
7. Select **Save**.

[Update your logpush job](https://developers.cloudflare.com/logs/logpush/logpush-job/log-output-options/) by adding `BotDetectionIDs` to the `output_options:` parameters.

---

## Availability

Detection IDs are available for Enterprise Bot Management customers.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/additional-configurations/","name":"Additional configurations"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/additional-configurations/detection-ids/","name":"Detection IDs"}}]}
```

---

---
title: Account takeover detections
description: Detection IDs for identifying and mitigating automated account takeover attacks.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Account takeover detections

Using the detection IDs below, you can detect and mitigate account takeover attacks. You can monitor the number of login requests for a given software and network combination, as well as the percentage of login errors. When it reaches a suspicious level, you can prevent these attacks by using [custom rules](https://developers.cloudflare.com/waf/custom-rules/), [rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/), and [Workers](https://developers.cloudflare.com/workers/).

| Detection ID | Description                                                                                                                                                                                                                                                                                                                                                                        |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 201326592    | Matches traffic that is making a suspicious amount of login failures to the zone.                                                                                                                                                                                                                                                                                                  |
| 201326593    | Matches traffic that is making a suspicious amount of login attempts to the zone.                                                                                                                                                                                                                                                                                                  |
| 201326598    | Sets a dynamic threshold based on the normal traffic that is unique to the zone. When the ID matches a login failure, Bot Management sets the [bot score](https://developers.cloudflare.com/bots/concepts/bot-score/) to 29 and uses [anomaly detection](https://developers.cloudflare.com/bots/concepts/bot-detection-engines/#anomaly-detection-enterprise) as its score source. |

Login endpoints

Not all login endpoints are automatically detected.

Cloudflare evaluates and automatically detects your website or application's login endpoint, but non-traditional login endpoints may not be recognized.

For example, if you have a non-traditional login endpoint, you should label it with `cf-log-in` using the [endpoint labeling service](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/). Once you have applied the `cf-log-in` label, Cloudflare will use the labeled endpoint for account takeover detection decisions.

## Challenges for account takeover detections

Cloudflare's [Managed Challenge](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/#managed-challenge) can limit brute-force attacks on your login endpoints.

To access account takeover detections:

* [  New dashboard ](#tab-panel-6680)
* [ Old dashboard ](#tab-panel-6681)

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. Select **Create rule** and choose **Custom rule**.
3. Fill out the form using **Bot Detection IDs** along with other necessary information.
4. Select **Save as draft** to return to the rule later, or **Deploy** to deploy the rule.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **WAF**.
3. Under **Custom rules**, select **Create rule**.
4. Fill out the form using **Bot Detection IDs** along with other necessary information.
5. Select **Save as draft** to return to the rule later, or **Deploy** to deploy the rule.

Rule example

```

(any(cf.bot_management.detection_ids[*] eq 201326593))


```

## Limit logins with account takeover detections

Rate limiting rules can limit the number of logins from a particular IP, JA4 fingerprint, or country.

To use rate limiting rules with account takeover detections:

* [  New dashboard ](#tab-panel-6682)
* [ Old dashboard ](#tab-panel-6683)

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. Select **Create rule** and choose **Rate limiting rule**.
3. Fill out the form using the **Custom expression builder** and `cf.bot_management_detection_ids` along with other necessary information.
4. Select **Save as draft** to return to the rule later, or **Deploy** to deploy the rule.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **WAF**.
3. Under **Rate limiting rules**, select **Create rule**.
4. Fill out the form using the **Custom expression builder** and `cf.bot_management_detection_ids` along with other necessary information.
5. Select **Save as draft** to return to the rule later, or **Deploy** to deploy the rule.

Enhanced with leaked credential detections

The rule can be enhanced with Leaked Credential Checks. Refer to the [WAF documentation](https://developers.cloudflare.com/waf/detections/leaked-credentials/) for more information on how to include leaked credentials and account takeover detections in a rate limiting rule.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/additional-configurations/","name":"Additional configurations"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/additional-configurations/detection-ids/","name":"Detection IDs"}},{"@type":"ListItem","position":5,"item":{"@id":"/bots/additional-configurations/detection-ids/account-takeover-detections/","name":"Account takeover detections"}}]}
```

---

---
title: Additional detections
description: Detection IDs for residential proxy traffic and other automated signals.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Additional detections

Cloudflare bot detection includes additional signals to catch different kinds of automated traffic.

Bot management customers automatically benefit from the residential proxy detection improvement below, which lowers the [bot score](https://developers.cloudflare.com/bots/concepts/bot-score/) for matched requests. Using the detection ID in [custom rules](https://developers.cloudflare.com/waf/custom-rules/) provides even more visibility and control over mitigating residential proxy traffic.

| Detection ID | Description                                                                                                                                                                                                                                                                                                    |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 50331651     | Observes traffic from residential proxy networks and similar commercial proxies. When the ID matches a request, Bot Management sets the bot score to 29 and uses [anomaly detection](https://developers.cloudflare.com/bots/concepts/bot-detection-engines/#anomaly-detection-enterprise) as its score source. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/additional-configurations/","name":"Additional configurations"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/additional-configurations/detection-ids/","name":"Detection IDs"}},{"@type":"ListItem","position":5,"item":{"@id":"/bots/additional-configurations/detection-ids/additional-detections/","name":"Additional detections"}}]}
```

---

---
title: Scraping detections
description: Detection IDs for identifying volumetric scraping attacks by ASN and fingerprint.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Scraping detections

Scraping behavioral detection IDs allow you to better protect your website from volumetric scraping attacks by identifying anomalous behavior. The detection IDs below are specifically designed to catch suspicious scraping activity at the zone level.

| Detection ID | Description                                                                                         |
| ------------ | --------------------------------------------------------------------------------------------------- |
| 50331648     | Observes patterns of requests sent to your zone, dynamically analyzing behavior by ASN.             |
| 50331649     | Observes patterns of requests sent to your zone, dynamically analyzing behavior by JA4 fingerprint. |

## Challenges for scraping detections

Cloudflare's [Managed Challenge](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/#managed-challenge) can limit scraping attacks on your website.

To access scraping detections:

* [  New dashboard ](#tab-panel-6684)
* [ Old dashboard ](#tab-panel-6685)

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. Select **Create rule** and choose **Custom rule**.
3. Fill out the form using **Bot Detection IDs** along with other necessary information.
4. Select **Save as draft** to return to the rule later, or **Deploy** to deploy the rule.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **WAF**.
3. Under **Custom rules**, select **Create rule**.
4. Fill out the form using **Bot Detection IDs** along with other necessary information.
5. Select **Save as draft** to return to the rule later, or **Deploy** to deploy the rule.

Rule example

```

(any(cf.bot_management.detection_ids[*] in {50331648 50331649}) and not cf.bot_management.verified_bot)


```

Best practice

If you are choosing to challenge as your rule action, ensure that you exclude any API calls on which you do not want to issue a challenge. To exclude requests to such paths, edit the [WAF custom rule](https://developers.cloudflare.com/waf/custom-rules/) to exclude the relevant paths.

Note

The matched traffic for detection IDs `50331648` and `50331649` is dynamically re-calculated, meaning a single fingerprint would not be permanently flagged unless it continues to behave suspiciously at all times.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/additional-configurations/","name":"Additional configurations"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/additional-configurations/detection-ids/","name":"Detection IDs"}},{"@type":"ListItem","position":5,"item":{"@id":"/bots/additional-configurations/detection-ids/scraping-detections/","name":"Scraping detections"}}]}
```

---

---
title: JA3/JA4 fingerprint
description: Profile SSL/TLS clients across requests using JA3 and JA4 fingerprints.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# JA3/JA4 fingerprint

[**JA3** ↗](https://github.com/salesforce/ja3) and [**JA4** ↗](https://github.com/FoxIO-LLC/ja4) **fingerprints** identify TLS clients based on how they initiate connections. Each client type (browser, bot, or application) has distinct connection characteristics, so the resulting fingerprint acts as a stable identifier across different destination IPs, ports, and certificates.

JA4 improves on JA3 by sorting ClientHello extensions, which reduces the number of unique fingerprints for modern browsers and makes grouping easier.

Note

JA3 and JA4 fingerprints are only available to Enterprise customers who have purchased Bot Management.

If you want to use JA4 fingerprints and Signals Intelligence, your Workers script must be able to handle the absence of any field in the array, including:

* The possibility that the JA4 fingerprint could be missing.
* The possibility that the `ja4Signals` array could be missing.
* Results with `NaN` or `Infinity` values will be excluded from the array.

```

{

  "ja4Signals": {

    "h2h3_ratio_1h": 0.98826485872269,

    "heuristic_ratio_1h": 7.288895722013e-05,

    "reqs_quantile_1h": 0.99905741214752,

    "uas_rank_1h": 901,

    "browser_ratio_1h": 0.93640440702438,

    "paths_rank_1h": 655,

    "reqs_rank_1h": 850,

    "cache_ratio_1h": 0.18918327987194,

    "ips_rank_1h": 662,

    "ips_quantile_1h": 0.99926590919495

  },

  "jaSignalsParsed": {

    "ratios": {

      "h2h3_ratio_1h": 0.98826485872269,

      "heuristic_ratio_1h": 7.288895722013e-05,

      "browser_ratio_1h": 0.93640440702438,

      "cache_ratio_1h": 0.18918327987194

    },

    "ranks": {

      "uas_rank_1h": 901,

      "paths_rank_1h": 655,

      "reqs_rank_1h": 850,

      "ips_rank_1h": 662

    },

    "quantiles": {

      "reqs_quantile_1h": 0.99905741214752,

      "ips_quantile_1h": 0.99926590919495

    }

  }

}


```

When JA4 Signals are missing, the output appears as follows:

```

{

  "ja4Signals": {},

  "jaSignalsParsed": {

    "ratios": {},

    "ranks": {},

    "quantiles": {}

  }

}


```

Note

This sample was generated using [Workers' Cloudflare Object script](https://developers.cloudflare.com/workers/examples/accessing-the-cloudflare-object/).

The JA3 or JA4 fingerprint is an SSL/TLS-based identifier and can be null or empty in logs under specific circumstances:

* Since JA3 and JA4 are calculated during the TLS (SSL) handshake, they will not be present for non-encrypted HTTP traffic.
* The field may be empty when a [Worker](https://developers.cloudflare.com/workers/) sends a request to a zone that is either internal to Cloudflare's network (O2O traffic that is not proxied) or to a third-party origin, or when a Worker is routing traffic to the target zone.
* The fingerprints may be absent when Bot Management itself is skipped for a request, as the feature is responsible for calculating and populating these values.
* With [TLS Session Resumption ↗](https://blog.cloudflare.com/tls-session-resumption-full-speed-and-secure/), once the initial TLS handshake is successfully completed, subsequent connections will be streamlined. This results in no further fingerprint calculation.

Generally, [O2O traffic](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/) should include JA3 or JA4 fingerprints unless a Worker is used to route traffic from the eyeball (client-facing) zone to the target zone.

## Analytics

To get more information about potential bot requests, use these JA3 and JA4 fingerprints in:

* [Bot Analytics](https://developers.cloudflare.com/bots/bot-analytics/#enterprise-bot-management)
* [Security Events](https://developers.cloudflare.com/waf/analytics/security-events/) and [Security Analytics](https://developers.cloudflare.com/waf/analytics/security-analytics/)
* [Analytics GraphQL API](https://developers.cloudflare.com/analytics/graphql-api/), specifically the **HTTP Requests** dataset
* [Logs](https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/zone/http%5Frequests/)

## Actions

To adjust how your application responds to specific fingerprints, use them with:

* [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/)
* [Transform Rules](https://developers.cloudflare.com/rules/transform/)
* [Cloudflare Workers](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties)

## Use cases

### Block or allow certain traffic

A group of similar requests may share the same JA3 fingerprint. For this reason, JA3 may be useful in blocking an incoming threat. For example, if you notice that a bot attack is not caught by existing defenses, create a [custom rule](https://developers.cloudflare.com/waf/custom-rules/) that blocks or challenges the JA3 used for the attack.

Alternatively, if existing defenses are blocking traffic that is actually legitimate, create a [custom rule](https://developers.cloudflare.com/waf/custom-rules/) with the _Skip_ action allowing the JA3 seen across good requests.

JA3 may also be useful if you want to immediately remedy false positives or false negatives with Bot Management.

### Allow mobile traffic

Often, mobile application traffic will produce the same JA3 fingerprint across devices and users. This means you can identify your mobile application traffic by its JA3 fingerprint.

Use the JA3 fingerprint to [allow traffic](https://developers.cloudflare.com/waf/custom-rules/use-cases/challenge-bad-bots/#adjust-for-mobile-traffic) from your mobile application, but block or challenge remaining traffic.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/additional-configurations/","name":"Additional configurations"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/additional-configurations/ja3-ja4-fingerprint/","name":"JA3/JA4 fingerprint"}}]}
```

---

---
title: Signals Intelligence
description: View aggregate intelligence data for JA4 fingerprints across Cloudflare traffic.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Signals Intelligence

Bot Management customers can view aggregate intelligence data for each [JA4 fingerprint](https://developers.cloudflare.com/bots/additional-configurations/ja3-ja4-fingerprint/) based on traffic across the Cloudflare network. Use this data to understand why a request received a specific bot score or to feed into your own machine learning models running in [Cloudflare Workers](https://developers.cloudflare.com/workers/) or at your origin.

Specifically, for each JA4 fingerprint, you will be able to access the following information:

* The percentage of traffic associated with browsers that Cloudflare sees.
* The percentage of traffic associated with known bots that Cloudflare sees.
* The number of networks Cloudflare sees actively using this fingerprint.
* The number of Cloudflare sites that see traffic from this fingerprint.
* The frequency that fingerprint requests caches content and generates errors.

You can also use these fields with [Workers AI](https://developers.cloudflare.com/workers-ai/) to build custom machine learning models.

## Signals Intelligence fields

Signals Intelligence fields show observations about a particular JA4 that Cloudflare has seen globally over the last hour.

| Field name           | Description                                                                                                                                                                                                                                       |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| h2h3\_ratio\_1h      | The ratio of HTTP/2 and HTTP/3 requests combined with the total number of requests for the JA4 fingerprint in the last hour. Higher values indicate a higher proportion of HTTP/2 and HTTP/3 requests compared to other protocol versions.        |
| heuristic\_ratio\_1h | The ratio of requests with a scoreSrc value of "heuristics" for the JA4 fingerprint in the last hour. Higher values suggest a larger proportion of requests being flagged by heuristic-based scoring.                                             |
| reqs\_quantile\_1h   | The quantile position of the JA4 fingerprint based on the number of requests across all fingerprints in the last hour. Higher values indicate a relatively higher number of requests compared to other fingerprints.                              |
| uas\_rank\_1h        | The rank of the JA4 fingerprint based on the number of distinct user agents across all fingerprints in the last hour. Lower values indicate a higher diversity of user agents associated with the fingerprint.                                    |
| browser\_ratio\_1h   | The ratio of requests originating from browser-based user agents for the JA4 fingerprint in the last hour. Higher values suggest a higher proportion of browser-based requests.                                                                   |
| paths\_rank\_1h      | The rank of the JA4 fingerprint based on the number of unique request paths across all fingerprints in the last hour. Lower values indicate a higher diversity of request paths associated with the fingerprint.                                  |
| reqs\_rank\_1h       | The rank of the JA4 fingerprint based on the number of requests across all fingerprints in the last hour. Lower values indicate a higher number of requests associated with the fingerprint.                                                      |
| cache\_ratio\_1h     | The ratio of cacheable responses for the JA4 fingerprint in the last hour. Higher values suggest a higher proportion of responses that can be cached.                                                                                             |
| ips\_rank\_1h        | The rank of the JA4 fingerprint based on the number of unique client IP addresses across all fingerprints in the last hour. Lower values indicate a higher number of distinct client IPs associated with the fingerprint.                         |
| ips\_quantile\_1h    | The quantile position of the JA4 fingerprint based on the number of unique client IP addresses across all fingerprints in the last hour. Higher values indicate a relatively higher number of distinct client IPs compared to other fingerprints. |

If you want to use JA4 fingerprints and Signals Intelligence, your Workers script must be able to handle the absence of any field in the array, including:

* The possibility that the JA4 fingerprint could be missing.
* The possibility that the `ja4Signals` array could be missing.
* Results with `NaN` or `Infinity` values will be excluded from the array.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/additional-configurations/","name":"Additional configurations"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/additional-configurations/ja3-ja4-fingerprint/","name":"JA3/JA4 fingerprint"}},{"@type":"ListItem","position":5,"item":{"@id":"/bots/additional-configurations/ja3-ja4-fingerprint/signals-intelligence/","name":"Signals Intelligence"}}]}
```

---

---
title: JavaScript Detections
description: Client-side JavaScript challenges that run on every request to identify automated traffic.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# JavaScript Detections

JavaScript Detections is a type of challenge separate from Cloudflare’s Challenge Pages or Turnstile. JavaScript Detections helps Cloudflare's [bot solutions](https://developers.cloudflare.com/bots/) identify automated requests.

While Challenge Pages and Turnstile rely on client-side signals to determine the authenticity of a request, Bot Management’s JavaScript Detections relies on client-side signals and runs on every single request made to your website.

## Process

JavaScript Detections is implemented on your website via a lightweight, invisible JavaScript code snippet that follows Cloudflare's [privacy standards ↗](https://www.cloudflare.com/privacypolicy/).

JavaScript is injected only in response to requests for HTML pages or page views, excluding AJAX calls. API and mobile application traffic is unaffected.

JavaScript Detections has a lifespan of 15 minutes. However, the code is injected again before the session expires. After page load, the script is deferred and utilizes a separate thread (where available) to ensure that performance impact is minimal. The snippets of JavaScript will contain a source pointing to the Challenge Platform, with paths that start with `/cdn-cgi/challenge-platform/…`

Once JavaScript Detections is injected on the HTML page, the visitor's browser will run the JavaScript code snippet and a `cf_clearance` cookie is issued to the visitor. The information in JavaScript Detections is stored in the `cf_clearance` cookie and is used to populate `js_detection.passed`.

* If the visitor is verified and a `cf_clearance` cookie is issued, it will contain the outcome: `cf.bot_management.js_detection.passed` \= `true`
* If the verification fails, the cookie will contain the outcome: `cf.bot_management.js_detection.passed` \= `false`

Note

The `cf_clearance` cookie cannot exceed the maximum size of 4096 bytes.

Warning

Enforcement against bots does **not** occur even if the cookie is flagged false.

You must enable JavaScript Detections and then create a custom WAF rule using the `cf.bot_management.js_detection.passed` field to block or challenge a failed request.

When the visitor encounters a WAF custom rule on your website, the rule will check the outcome of the `cf_clearance` cookie. The outcome of the `cf_clearance` cookie determines whether the request passes, or is blocked or challenged.

Refer to the steps below to enable and enforce JavaScript Detections.

## 1\. Enable JavaScript Detections

For Bot Fight Mode customers, [JavaScript Detections](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/javascript-detections/) is automatically enabled and cannot be disabled.

For Super Bot Fight Mode and Bot Management for Enterprise customers, [JavaScript Detections](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/javascript-detections/) is optional.

* [  New dashboard ](#tab-panel-6865)
* [ Old dashboard ](#tab-panel-6866)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Under your bot traffic plan configurations, select the edit icon for **JS detections** and turn **JavaScript Detections** on.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Bots**.
3. Select **Configure Bot Management**.
4. For **JavaScript Detections**, switch the toggle to **On**.

For more details on how to set up bot protection, refer to the [Bots documentation](https://developers.cloudflare.com/bots/get-started/).

## 2\. Enforce execution of JavaScript Detections

Once you enable JavaScript detections, you must use the `cf.bot_management.js_detection.passed` field to create [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/) (or the `request.cf.botManagement.jsDetection.passed` variable in [Workers](https://developers.cloudflare.com/workers/)).

When adding this field to WAF custom rules, it is used on endpoints expecting browser traffic (avoiding native mobile applications or websocket endpoints), after a user's first request to your application (Cloudflare needs at least one HTML request before injecting JavaScript detection), and with the Managed Challenge action, because there are legitimate reasons a user might not have passed a JavaScript Detection challenge (network issues, ad blockers, disabled JavaScript in browser, native mobile applications).

### Prerequisites

* You must have an [Enterprise Bot Management](https://developers.cloudflare.com/bots/plans/bm-subscription/) subscription.
* You must have JavaScript Detections enabled on your zone.
* You must have [updated your Content Security Policy headers](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/javascript-detections/#if-you-have-a-content-security-policy-csp) for JavaScript detections.
* You must not run this field on websocket endpoints.
* You must use the field in a custom rules expression that expects only browser traffic.
* The action should always be a managed challenge in case a legitimate user has not received the challenge for network or browser reasons.
* The path specified in the rule builder should never be the first HTML page a user visits when browsing your site.

The `cf.bot_management.js_detection.passed` field should never be used in a WAF custom rule that matches a visitor's first request to a site. It is necessary to have at least one HTML request before Cloudflare can inject JavaScript detection.

* [ WAF rule example ](#tab-panel-6863)
* [ Workers example ](#tab-panel-6864)

```

(http.request.uri.path eq "/api/v4/user/create" and http.request.method eq "POST" and not cf.bot_management.verified_bot)

and (cf.bot_management.score lt 30 or !cf.bot_management.js_detection.passed)


```

JavaScript

```

"botManagement": {

"jsDetection": {

    "passed": false

}

}


```

Refer to the [WAF documentation](https://developers.cloudflare.com/waf/custom-rules/create-dashboard/) for more information on creating a custom rule.

## API

If you enable JavaScript Detections via the dashboard, Cloudflare will insert a script tag in all HTML pages served on your website. If you would prefer to limit where JavaScript Detections is served, you can do so with the JavaScript Detections API script.

The JavaScript Detections API allows you more granular control over when and where JavaScript Detections is injected on your website, as well as an option for callback handling (for logging or other additional actions).

You can explicitly add a script reference to `/cdn-cgi/challenge-platform/scripts/jsd/api.js` and your own code calling `window.cloudflare.jsd.executeOnce` on specific HTML pages of your website.

Warning

It is not recommended to combine both approaches (zone-wide toggle and the manual injection). If you want to selectively deploy JavaScript Detections only on certain pages, disable JavaScript Detections via the Cloudflare dashboard and use the JavaScript Detections API exclusively.

The following script must be added to every page that you wish to have JavaScript Detections enabled:

```

<script>


function jsdOnload(){

  window.cloudflare.jsd.executeOnce(

    {

      callback: function(result){

        console.log('jsd outcome', result);

      }

    }

  );

}

</script>

<script src="/cdn-cgi/challenge-platform/scripts/jsd/api.js?onload=jsdOnload" async>


```

Note

`result` \= `success` or `error` only refers to the execution of JavaScript Detections. It does not indicate whether a visitor is a human or a bot.

## Considerations

JavaScript Detections does not guarantee a specific bot score.

* If the JavaScript Detections injection or execution fails and `cf.bot_management.js_detection.passed` \= `false`, a separate Bot Management heuristic can still yield a `1` or higher bot score, independent of JavaScript Detections.
* If the JavaScript Detections passes, the final bot score may still be `1` due to other detection heuristics (for example, known malicious IP, signature detection, and more), resulting in `js_detection.passed` \= `true`, but `score` \= `1`.

## Limitations

### If you enabled Bot Management before June 2020

Customers who enabled Enterprise Bot Management before June 2020 do not have JavaScript Detections enabled by default (unless specifically requested). These customers can still enable the feature in the Cloudflare dashboard.

### If it is the first request to your website

The first request from a new client to your website or application will generally not have JavaScript Detections data (`cf.bot_management.js_detection.passed` \= `false`). This is because Cloudflare needs at least one HTML request before injecting JavaScript Detection and issuing the `cf_clearance` cookie.

Subsequent requests can include a `cf_clearance` cookie if JavaScript ran successfully.

### If you have a Content Security Policy (CSP)

If you have a Content Security Policy (CSP), you need to take additional steps to implement JavaScript Detections:

* Ensure that anything under `/cdn-cgi/challenge-platform/` is allowed. Your CSP should allow scripts served from your origin domain (`script-src self`).
* For `nonce` script tags:  
   * If your CSP uses a `nonce` for script tags, Cloudflare will add these nonces to the scripts it injects by parsing your CSP response header.  
   * If your CSP does not use `nonce` for script tags and **JavaScript Detections** is enabled, you may see a console error such as `Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-b123b8a70+4jEj+d6gWI9U6IilUJIrlnRJbRR/uQl2Jc='), or a nonce ('nonce-...') is required to enable inline execution.` We highly discourage the use of `unsafe-inline` and instead recommend the use CSP `nonces` in script tags which we parse and support in our CDN.

Warning

JavaScript Detections is not supported with `nonce` set via `<meta>` tags.

### If you have ETags

Enabling JavaScript Detections (JSD) will strip [ETags](https://developers.cloudflare.com/cache/reference/etag-headers/) from HTML responses where JSD is injected.

### If your origin sends a `no-transform` header

If the origin response includes a `Cache-Control: no-transform` directive, Cloudflare does not inject the JavaScript Detections script. The `cf.bot_management.js_detection.passed` field will show as `missing` for these requests.

To use JavaScript Detections, remove the `no-transform` directive from `Cache-Control` response headers on pages where you want JavaScript Detections to run. For more information, refer to [Cache-Control directives](https://developers.cloudflare.com/cache/concepts/cache-control/#interaction-with-other-cloudflare-features).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/challenge-types/","name":"Available Challenges"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/challenge-types/javascript-detections/","name":"JavaScript Detections"}}]}
```

---

---
title: robots.txt setting
description: Manage a robots.txt file to direct AI bot operators on content scraping permissions.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# robots.txt setting

AI companies use crawlers to collect website content for training language models, generating search answers, and other purposes. A `robots.txt` file at the root of your domain tells these crawlers which content they should or should not access. When you turn on the managed `robots.txt` setting, Cloudflare generates and maintains a `robots.txt` file that instructs known AI crawlers to stay away from your content.

`robots.txt` compliance is voluntary. The file expresses your preferences, but it does not prevent crawlers from accessing your content at a technical level. Some crawler operators may disregard your `robots.txt` directives (instructions like `Disallow: /`) and crawl your content regardless.

Note

If you want to enforce crawl blocking rather than request it, use [AI Crawl Control](https://developers.cloudflare.com/ai-crawl-control/features/manage-ai-crawlers/). You can also use both features together — `robots.txt` to express your preferences and AI Crawl Control to enforce them.

## Compatibility with existing `robots.txt` files

Cloudflare detects whether your origin server already has a `robots.txt` file and adjusts accordingly — either merging with your existing file or creating one from scratch.

### Existing robots.txt file

If your website already has a `robots.txt` file — verified by an HTTP `200` response — Cloudflare will prepend our managed `robots.txt` before your existing `robots.txt`, combining both into a single response.

For example, without this feature enabled, the `robots.txt` content of `crawlstop.com` would be:

Feature not enabled

```

User-agent: *

Disallow: /lp

Disallow: /feedback

Disallow: /langtest


Sitemap: https://www.crawlstop.com/sitemap.xml


```

With the managed `robots.txt` enabled, Cloudflare will prepend our managed content before your original content, resulting in what you can view at [https://www.crawlstop.com/robots.txt ↗](https://www.crawlstop.com/robots.txt).

Feature enabled

```

# As a condition of accessing this website, you agree to abide by the

# following content signals:


# (a)  If a content-signal = yes, you may collect content for the

#      corresponding use.

# (b)  If a content-signal = no, you may not collect content for the

#      corresponding use.

# (c)  If the website operator does not include a content signal for a

#      corresponding use, the website operator neither grants nor restricts

#      permission via content signal with respect to the corresponding use.


# The content signals and their meanings are:


# search: building a search index and providing search results (e.g., returning

#         hyperlinks and short excerpts from your website's contents). Search

#         does not include providing AI-generated search summaries.

# ai-input: inputting content into one or more AI models (e.g., retrieval

#           augmented generation, grounding, or other real-time taking of

#           content for generative AI search answers).

# ai-train: training or fine-tuning AI models.


# ANY RESTRICTIONS EXPRESSED VIA CONTENT SIGNALS ARE EXPRESS RESERVATIONS OF

# RIGHTS UNDER ARTICLE 4 OF THE EUROPEAN UNION DIRECTIVE 2019/790 ON COPYRIGHT

# AND RELATED RIGHTS IN THE DIGITAL SINGLE MARKET.


# BEGIN Cloudflare Managed content


User-Agent: *

Content-signal: search=yes, ai-train=no

Allow: /


User-agent: Amazonbot

Disallow: /


User-agent: Applebot-Extended

Disallow: /


User-agent: Bytespider

Disallow: /


User-agent: CCBot

Disallow: /


User-agent: ClaudeBot

Disallow: /


User-agent: Google-Extended

Disallow: /


User-agent: GPTBot

Disallow: /


User-agent: meta-externalagent

Disallow: /


# END Cloudflare Managed Content

User-agent: *

Disallow: /lp

Disallow: /feedback

Disallow: /langtest


Sitemap: https://www.crawlstop.com/sitemap.xml


```

### No robots.txt file

If your website does not have a `robots.txt` file, Cloudflare creates a new file with managed `Disallow` rules for known AI crawlers and serves it for you.

## Implementation

To implement a `robots.txt` file on your domain:

* [  New dashboard ](#tab-panel-6686)
* [ Old dashboard ](#tab-panel-6687)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **Bot traffic**.
3. Go to **Instruct AI bot traffic with robots.txt**.
4. Turn on **Instruct AI bot traffic with robots.txt**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Bots**.
3. Select **Configure Bot Fight Mode**.
4. Turn on **Instruct bot traffic with robots.txt**.

## Content Signals Policy

Content Signals are a set of machine-readable directives in a `robots.txt` file that categorize how crawlers may use your content. The three categories are `search` (building a search index), `ai-input` (feeding content into AI models for real-time answers), and `ai-train` (training or fine-tuning AI models).

Domains on the Free plan that do not have their own `robots.txt` file and do not use the managed `robots.txt` feature will display the Content Signals Policy when a crawler requests the `robots.txt` file for your domain.

The Content Signals Policy defines these categories but does not express any specific preferences about your content. To set preferences (for example, `ai-train=no`), turn on the managed `robots.txt` feature.

Content Signals Policy

```

# As a condition of accessing this website, you agree to abide by the

# following content signals:


# (a)  If a content-signal = yes, you may collect content for the

#      corresponding use.

# (b)  If a content-signal = no, you may not collect content for the

#      corresponding use.

# (c)  If the website operator does not include a content signal for a

#      corresponding use, the website operator neither grants nor restricts

#      permission via content signal with respect to the corresponding use.


# The content signals and their meanings are:


# search: building a search index and providing search results (e.g., returning

#         hyperlinks and short excerpts from your website's contents). Search

#         does not include providing AI-generated search summaries.

# ai-input: inputting content into one or more AI models (e.g., retrieval

#           augmented generation, grounding, or other real-time taking of

#           content for generative AI search answers).

# ai-train: training or fine-tuning AI models.


# ANY RESTRICTIONS EXPRESSED VIA CONTENT SIGNALS ARE EXPRESS RESERVATIONS OF

# RIGHTS UNDER ARTICLE 4 OF THE EUROPEAN UNION DIRECTIVE 2019/790 ON COPYRIGHT

# AND RELATED RIGHTS IN THE DIGITAL SINGLE MARKET.


```

Cloudflare's Content Signals Policy is included by default in the `robots.txt` file when you turn on **robots.txt setting**.

If you would like to opt out of displaying the policy in your `robots.txt` file, you can uncheck **Display Content Signals Policy** under **Control AI Crawlers** in your zone's overview.

[ Go to **Overview** ](https://dash.cloudflare.com/?to=/:account/:zone/) 

Alternatively, you can use [Security Settings](#implementation).

Warning

Google Search Console may occasionally report `Syntax not understood` for Content Signals and newer directives in the `robots.txt` standard. However, we have observed no impact on crawling rates or SEO as a result of these reports.

## Availability

Managed `robots.txt` for AI crawlers is available on all plans.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/additional-configurations/","name":"Additional configurations"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/additional-configurations/managed-robots-txt/","name":"robots.txt setting"}}]}
```

---

---
title: Sequence rules
description: Detect and mitigate bot traffic based on cookie-based request sequences.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Sequence rules

[Sequence rules](https://developers.cloudflare.com/bots/additional-configurations/sequence-rules/) uses cookies to track the order of requests a user has made and the time between requests and makes them available via [Cloudflare Rules](https://developers.cloudflare.com/rules/). This allows you to write rules that match valid or invalid sequences. The specific cookies used to validate sequences are called sequence cookies.

`431` error

Too many concurrent requests to your zone may add cookies that create a header that is too large, causing a `431` error.

## Prerequisites

* Your account must have the Fraud Detection subscription.
* Each zone must configure the endpoints to track via Endpoint Management.

You can [build a sequence custom rule via the Cloudflare dashboard](#build-a-sequence-custom-rule-via-the-cloudflare-dashboard) or [using the API](#manage-sequence-rules-via-the-api).

---

## Availability

These sequence fields are available in:

* [Custom rules](https://developers.cloudflare.com/waf/custom-rules/) (`http_request_firewall_custom` phase)
* [Rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/) (`http_request_ratelimit`)
* [Bulk Redirects](https://developers.cloudflare.com/workers/examples/bulk-redirects/) (`http_request_redirect`)
* [Request Header Transform Rules](https://developers.cloudflare.com/rules/transform/response-header-modification/) (`http_request_late_transform`)

| Field name                             | Description                                                                                                                                                                                                                                                                  | Example value                          |
| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
| cf.sequence.current\_opString          | This field contains the ID of the operation that matches the current request. If the current request does not match any operations defined in Endpoint Management, it will be an empty string.                                                                               | c821cc00                               |
| cf.sequence.previous\_opsArray<String> | This field contains an array of the prior operation IDs in the sequence, ordered from most to least recent. It does not include the current request.  If an operation is repeated, it will appear multiple times in the sequence.                                            | \["f54dac32", "c821cc00", "a37dc89b"\] |
| cf.sequence.msec\_since\_opMap<Number> | This field contains a map where the keys are operation IDs and the values are the number of milliseconds since that operation has most recently occurred.  This does not include the current request or operation as it only factors in previous operations in the sequence. | {"f54dac32": 1000, "c821cc00": 2000}   |

---

## Build a sequence custom rule via the Cloudflare dashboard

* [  New dashboard ](#tab-panel-6688)
* [ Old dashboard ](#tab-panel-6689)

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. To create a new empty rule, select **Create rule** \> **Custom rules**.
3. Enter a descriptive name for the rule in **Rule name**.
4. Under **When incoming requests match**, use the **Field** drop-down list to filter by **Sequences** and select from:  
   * Current Operation  
   * Previous Operations  
   * Elapsed time
5. Under **Value**, select the edit icon to use Builder and build a sequence on the side panel.
6. Under **Select a hostname for this sequence**, choose all or a specific hostname from the dropdown list. Optionally, you can use the search bar to search for a specific hostname.
7. From the **Methods** dropdown list, choose all methods or a specific request method.
8. Select the checkbox for each endpoint in the order that you want them to appear in the sequence.
9. Set the time to complete.
10. Select **Save**.
11. Under **Then take action**, select the rule action in the **Choose action** dropdown. For example, selecting _Block_ tells Cloudflare to refuse requests that match the conditions you specified.
12. (Optional) If you selected the _Block_ action, you can configure a custom response.
13. Under **Place at**, select the order of when the rule will fire.
14. To save and deploy your rule, select **Deploy**. If you are not ready to deploy your rule, select **Save as Draft**.

Note

The fields in the custom rule are populated as a grouped sequence based on the values that you entered on Builder.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **WAF** \> **Custom rules**.
3. To create a new empty rule, select **Create rule**.
4. Enter a descriptive name for the rule in **Rule name**.
5. Under **When incoming requests match**, use the **Field** drop-down list and select:  
   * Current Operation  
   * Previous Operations  
   * Elapsed time
6. Under **Value**, build a sequence by selecting a hostname for the sequence.
7. Select the checkbox for each endpoint in the order that you want them to appear in the sequence.
8. Set the time to complete.
9. Select **Save**.
10. Under **Then take action**, select the rule action in the **Choose action** dropdown. For example, selecting _Block_ tells Cloudflare to refuse requests that match the conditions you specified.
11. (Optional) If you selected the _Block_ action, you can configure a custom response.
12. Under **Place at**, select the order of when the rule will fire.
13. To save and deploy your rule, select **Deploy**. If you are not ready to deploy your rule, select **Save as Draft**.

---

## Manage sequence rules via the API

### Enable sequence rules

1. [Create an API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) if you do not already have one. The API token must include the _Zone_ \> _Fraud Detection_ \> _Edit_ permission. 2\. [Get the zone ID](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/) for the zone(s) where you want to enable sequence rules. 3\. [Add the endpoints](https://developers.cloudflare.com/api-shield/management-and-monitoring/) that you want to track in your sequence rules using API Shield's Endpoint Management and make note of the short ID. 4\. Enable the sequence cookie by adding your API token and zone ID to the following API call.

Note

The short ID will not be visible until your account team has enabled this feature for you.

API call

```

curl --request PUT \

https://api.cloudflare.com/client/v4/zones/{zone_id}/fraud_detection/sequence_cookies \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{"enabled": true}'


```

1. Use the expression editor to write sequence or timing based rules via [custom rules](https://developers.cloudflare.com/waf/custom-rules/), [rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/), or [transform rules](https://developers.cloudflare.com/rules/transform/). You can put these rules in log only mode to monitor.

Note

When you enable sequence rules, Cloudflare will start setting cookies for all requests that match your endpoints.

Once you have enabled sequence rules, the rules fields will be populated and you can now use the new fields in your rules.

### Disable sequence rules

Disabling sequence rules will stop the rules fields from being populated. If you still have rules deployed which depend on these fields, those rules may not behave as intended. Remove or disable any rules that rely on sequence fields before disabling sequence rules.

To disable sequence rules:

1. [Create an API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) if you do not already have one. The API token must include the _Zone_ \> _Fraud Detection_ \> _Edit_ permission. 2\. [Get the zone ID](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/) for the zone(s) where you want to enable sequence rules. 3\. [Add the endpoints](https://developers.cloudflare.com/api-shield/management-and-monitoring/) that you want to track in your sequence rules using API Shield's Endpoint Management and make note of the short ID. 4\. Disable the sequence cookie using your API token, zone ID, and by setting `enabled` to `false` on the following API call.

Note

The short ID will not be visible until your account team has enabled this feature for you.

API call

```

curl --request PUT https://api.cloudflare.com/client/v4/zones/{zone_id}/fraud_detection/sequence_cookies \

--header "Authorization: Bearer <API_TOKEN>" \

--data '{"enabled": false}'


```

---

## Rules fields

Sequence rules introduces three new fields to Cloudflare Rules. All of these fields reference operations by their short ID. Accounts that have the Fraud Detection subscription can refer to the short ID by viewing the endpoint details via **API Shield** \> **Endpoint Management** in the Cloudflare dashboard. Accounts without Fraud Detection do not have access to this field.

Cloudflare only stores up to the 10 most recent operations in a sequence for up to one hour. If there are more than 10 operations in the sequence, older operations will be dropped and will not be included in the following fields. Similarly, if an operation happened more than one hour ago, it will also not be included in the following fields.

### Example rules

The customer must request endpoint A before endpoint B.

Valid sequence

```

cf.sequence.current_op eq "bbbbbbbb" and

any(cf.sequence.previous_ops[*] == "aaaaaaaa")


```

Invalid sequence

```

cf.sequence.current_op eq "bbbbbbbb" and

not any(cf.sequence.previous_ops[*] == "aaaaaaaa")


```

Customer must request endpoint A at least one second before endpoint B.

Valid sequence

```

cf.sequence.current_op eq "bbbbbbbb" and

cf.sequence.msec_since_op["aaaaaaaa"] ge 1000


```

Invalid sequence

```

cf.sequence.current_op eq "bbbbbbbb" and

not cf.sequence.msec_since_op["aaaaaaaa"] ge 1000


```

---

## Limitations

Cloudflare only supports HTTPS requests since our cookies set the `Secure` attribute.

---

## Availability

Sequence rules is currently in private beta. If you would like to be included in the beta, contact your account team.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/additional-configurations/","name":"Additional configurations"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/additional-configurations/sequence-rules/","name":"Sequence rules"}}]}
```

---

---
title: Static resource protection
description: Extend bot protection to static resources like images, CSS, and JavaScript files.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Static resource protection

Pro, Business, and Enterprise customers can use Cloudflare's bot solutions to protect their static resources from bots.

Warning

If you enable static resource protection, you may block good bots — like mail clients — that routinely fetch static resources. Make sure you understand your existing infrastructure before enabling this feature.

## Super Bot Fight Mode

To enable this feature as a Pro or Business customer or an Enterprise customer without Bot Management:

* [  New dashboard ](#tab-panel-6690)
* [ Old dashboard ](#tab-panel-6691)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **Bot traffic**.
3. Go to **Super Bot Fight Mode**.
4. Under **Configurations**, select the edit icon for **Static resource protection** and turn it on.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/login), and select your account and domain.
2. Go to **Security** \> **Bots**.
3. Select **Configure Super Bot Fight Mode**.
4. For **Static resource protection**, select **On**.

Warning

The **Static Resource Protection** setting will only activate if at least one of the bot categories (definite, likely, or verified) is _not_ set to `Allow`. If all categories are set to `Allow`, this setting will not have any impact since it works alongside these bot settings as part of the managed rules.

## Bot Management for Enterprise

Static resources are protected by default when you create [custom rules](https://developers.cloudflare.com/waf/custom-rules/) using `cf.bot_management.score`.

To exclude static resources, you would need to include `not (cf.bot_management.static_resource)` as part of your custom rule.

## Which files are protected?

Static resources are files with the following extensions:

`ico|jpg|png|jpeg|gif|css|js|tif|tiff|bmp|pict|webp|svg|svgz|class|jar|txt|csv|doc|docx|xls|xlsx|pdf|ps|pls|ppt|pptx|ttf|otf|woff|woff2|eot|eps|ejs|swf|torrent|midi|mid|m3u8|m4a|mp3|ogg|ts`

Additionally, the `/.well-known/` URL path and all elements in it are considered a static resource, regardless of the file extension.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/additional-configurations/","name":"Additional configurations"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/additional-configurations/static-resources/","name":"Static resource protection"}}]}
```

---

---
title: Bots
description: Automated software programs that interact with websites and APIs.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Bots

A **bot** is a software application programmed to do certain tasks.

Bots can be used for good (chatbots, search engine crawlers) or for evil (inventory hoarding, credential stuffing).

More information

For more background, refer to [What is a bot? ↗](https://www.cloudflare.com/learning/bots/what-is-a-bot/).

## Verified bots and signed agents

Cloudflare maintains an internal directory of [verified bot](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/) and [signed agents](https://developers.cloudflare.com/bots/concepts/bot/signed-agents/) that are associated with search engine optimization (SEO), website monitoring, and more.

You can use this directory to prevent any bot protection measures from impacting otherwise helpful bots and agents, such as search crawlers.

For a partial list of verified bots and signed agents, refer to [Cloudflare Radar ↗](https://radar.cloudflare.com/verified-bots).

Note

The method for allowing or blocking verified bots depends on [your plan](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/#availability).

## AI bots

To prevent AI-related usage of your site content (such as training language models or generating search answers), you can turn on a managed rule that blocks known AI crawlers that use data for training models ("AI Bots"). A managed rule is a rule that Cloudflare maintains and updates — you turn it on, but you do not write or edit the rule yourself.

### Which bots are blocked

When you enable this feature, Cloudflare will block the following bots:

* `Amazonbot` (Amazon)
* `Applebot` (Apple)
* `Bytespider` (ByteDance)
* `ClaudeBot` (Anthropic)
* `DuckAssistBot` (DuckDuckGo)
* `Google-CloudVertexBot` (Google)
* `GoogleOther` (Google)
* `GPTBot` (OpenAI)
* `Meta-ExternalAgent` (Meta)
* `PetalBot` (Huawei)
* `TikTokSpider` (ByteDance)
* `CCBot` (Common Crawl)

In addition to this list, [verified bots ↗](https://radar.cloudflare.com/bots#verified-bots) that are classified as AI crawlers, as well as a number of unverified bots that behave similarly, are included in the rule. This rule does not include verified bots that fall into the `Search Engine` categories.

These categories, and the bots classified in these categories, may change from time to time.

If you are a bot operator and feel your bot may have been incorrectly categorized, [add your bot to the list of verified bots ↗](https://dash.cloudflare.com/?to=/:account/configurations/verified-bots).

### How it works

When you enable this feature, Cloudflare detects and blocks two categories of AI bots:

* **Well-behaved AI crawlers** that comply with `robots.txt`, respect crawl rates, and do not hide their behavior from your website.
* **Evasive AI crawlers** that do not follow these conventions but are detected through additional signatures.

### Rule evaluation order

Cloudflare evaluates bot-related rules in a specific order. When a request matches a rule and receives a terminating action (such as block or challenge), it does not continue to later rules in the sequence.

1. **Custom rules** (WAF custom rules you create) — evaluated first.
2. **Block AI bots** (the managed AI rule) — evaluated second.
3. **Other Super Bot Fight Mode rules** (definitely automated, likely automated, verified bots) — evaluated last.

The Block AI bots rule takes precedence over all other Super Bot Fight Mode rules. For example, if you have enabled **Block AI bots** and **Allow verified bots**, verified AI bots will still be blocked.

For Bot Management customers, custom rules run before the Block AI bots rule. If your custom rule challenges definitely automated traffic, AI bots will receive that challenge instead of reaching the Block AI bots rule. Because the challenge is a terminating action, Cloudflare does not evaluate the request against later rules in the sequence.

The SBFM settings for verified, definitely automated, and likely bots also affect evaluation. If these settings are set to `allow`, the request is not matched to any SBFM rule and proceeds to the next phase — where the Block AI bots rule can still block it. If the setting is `block`, the request is blocked in the earlier phase and does not reach the AI rule at all. If the setting is `challenge`, the request matches a rule and receives a terminating action, so it will not continue to later rules.

For self-serve non-Bot Management customers, all rules for verified, definitely automated, and likely bots run in the phase following the AI bots rule.

flowchart LR
accTitle: Super Bot Fight Mode and custom rules execution order diagram
accDescr: This diagram details the execution order of custom rules before Super Bot Fight Mode managed rules.
A[Custom rules] --> B[Block AI bots<br>managed rule] --> C[Other SBFM managed rules]

This feature is available on all Cloudflare plans.

Note

The method for blocking AI bots depends on [your plan](https://developers.cloudflare.com/bots/get-started/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/concepts/bot/","name":"Bots"}}]}
```

---

---
title: Bot detection engines
description: Heuristics, machine learning, and behavioral analysis engines used to detect bots.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Bot detection engines

Cloudflare uses multiple detection engines because different bot types require different detection strategies. Simple bots can be caught by pattern matching against known signatures, while sophisticated bots require machine learning and behavioral analysis.

The engines available to your domain depend on your plan.

## Heuristics

The **Heuristics** engine processes all requests. Cloudflare conducts a number of heuristic checks to identify automated traffic, and requests are matched against a growing database of malicious fingerprints.

## JavaScript detections

The [**JavaScript Detections (JSD)**](https://developers.cloudflare.com/bots/additional-configurations/javascript-detections/) engine identifies headless browsers and other malicious fingerprints. This engine performs a lightweight, invisible JavaScript injection on the client side of any request while honoring our [strict privacy standards ↗](https://www.cloudflare.com/privacypolicy/). We do not collect any personally identifiable information during the process. The JSD engine either blocks, challenges, or passes requests to other engines.

JSD is completely optional. To adjust your settings, configure Super Bot Fight Mode from **Security** \> **Bots**.

## Machine Learning (Business and Enterprise)

The **Machine Learning (ML)** engine accounts for the majority of all detections, distinguishing between human and bot traffic. This approach leverages our global network, which proxies billions of requests daily, to identify both automated and human traffic.

The ML system uses a supervised machine learning methodology to determine the final Bot Score (1–99).

The core model relies on the following process:

* Input Variables (X): Various request features (headers, session characteristics, and browser signals) collected from traffic across the Cloudflare network.
* Output Variable (Y): The predicted probability that a client is human (such as the probability of successfully solving a Challenge). This probability is mapped to the final 1–99 Bot Score.

We constantly train the ML engine on a periodic basis using vast, anonymized data to ensure it remains accurate and adapts to new threats. Customers can analyze the request features used by these models via their own logs, such as Cloudflare [Logpull](https://developers.cloudflare.com/logs/logpull/) or [Logpush](https://developers.cloudflare.com/logs/logpush/).

The ML engine identifies _likely automated_ traffic.

## Anomaly detection (Enterprise)

Deprecation notice

Cloudflare is deprecating the Anomaly Detection engine and is not onboarding new customers. Future behavioral detections will cover the same detection areas.

The **Anomaly Detection (AD)** engine is an optional detection engine that uses a form of unsupervised learning. Cloudflare records a baseline of your domain's traffic and uses the baseline to intelligently detect outlier requests. This approach is user agent-agnostic and can be turned on or off by your account team.

Cloudflare does not recommend AD for domains that use [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/) or expect large amounts of API traffic. The AD engine immediately gives automated requests a score of one.

## Notes on detection

Cloudflare uses the `__cf_bm` cookie to smooth out the bot score and reduce false positives for actual user sessions.

The Bot Management cookie measures a single user's request pattern and applies it to the machine learning data to generate a reliable bot score for all of that user's requests.

For more details, refer to [Cloudflare Cookies](https://developers.cloudflare.com/fundamentals/reference/policies-compliances/cloudflare-cookies/).

You can disable the `__cf_bm` cookie using the `bm_cookie_enabled` field [via the API](https://developers.cloudflare.com/api/resources/bot%5Fmanagement/methods/update/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/concepts/bot-detection-engines/","name":"Bot detection engines"}}]}
```

---

---
title: Bot scores
description: Scores from 1 to 99 indicating the likelihood a request came from a bot.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Bot scores

A bot score is a score from _1_ to _99_ that indicates how likely that request came from a bot.

For example, a score of 1 means Cloudflare is quite certain the request was automated, while a score of 99 means Cloudflare is quite certain the request came from a human.

You can use bot scores in [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/) to block, challenge, or allow requests based on their score. Bot scores are also available in [Workers](https://developers.cloudflare.com/workers/) to customize application behavior. For more details, refer to [Bot Management variables](https://developers.cloudflare.com/bots/reference/bot-management-variables/).

Note

Granular bot scores are only available to Enterprise customers who have purchased Bot Management. All other customers can only access this information through [bot groupings](#bot-groupings) in Bot Analytics.

## Bot groupings

Customers with a Pro plan or higher can automatically see bot traffic divided into groups by going to **Security** \> **Bots**.

| Category             | Range                                                                                  |
| -------------------- | -------------------------------------------------------------------------------------- |
| **Not computed**     | Bot scores of 0.                                                                       |
| **Automated**        | Bot scores of 1.                                                                       |
| **Likely automated** | Bot scores of 2 through 29.                                                            |
| **Likely human**     | Bot scores of 30 through 99.                                                           |
| **Verified bot**     | Non-malicious automated traffic (used to power search engines and other applications). |

Note

Bot scores are not computed for requests to paths that are handled by Cloudflare and will never be blocked or forwarded to the origin. Note that some features that are enabled before Bot Management, such as Redirect Rules, may result in requests not being scored.

## How Cloudflare generates bot scores

The following detection engines only apply to Enterprise Bot Management. For specific details about the engines included in your plan, refer to [Plans](https://developers.cloudflare.com/bots/plans/).

### Heuristics

Catches automated traffic through pattern matching against a database of known malicious fingerprints.

The **Heuristics** engine processes all requests. Cloudflare conducts a number of heuristic checks to identify automated traffic, and requests are matched against a growing database of malicious fingerprints.

The Heuristics engine gives automated requests a score of 1 for high-confidence, deterministic detections. Occasionally, heuristics will set a score of 29 in cases where Cloudflare has identified automated traffic and is still assessing traffic overlap.

### Machine learning

Catches sophisticated bots by analyzing request features across billions of daily requests. Produces most scores between 2 and 99.

The **Machine Learning (ML)** engine accounts for the majority of all detections, distinguishing between human and bot traffic. This approach leverages our global network, which proxies billions of requests daily, to identify both automated and human traffic.

The ML system uses a supervised machine learning methodology to determine the final Bot Score (1–99).

The core model relies on the following process:

* Input Variables (X): Various request features (headers, session characteristics, and browser signals) collected from traffic across the Cloudflare network.
* Output Variable (Y): The predicted probability that a client is human (such as the probability of successfully solving a Challenge). This probability is mapped to the final 1–99 Bot Score.

We constantly train the ML engine on a periodic basis using vast, anonymized data to ensure it remains accurate and adapts to new threats. Customers can analyze the request features used by these models via their own logs, such as Cloudflare [Logpull](https://developers.cloudflare.com/logs/logpull/) or [Logpush](https://developers.cloudflare.com/logs/logpush/).

### Anomaly detection

Detects outlier requests by comparing traffic against a learned baseline for your specific site.

Deprecation notice

Cloudflare is deprecating the Anomaly Detection engine and is not onboarding new customers. Future behavioral detections will cover the same detection areas.

The **Anomaly Detection (AD)** engine is an optional detection engine that uses a form of unsupervised learning. Cloudflare records a baseline of your domain's traffic and uses the baseline to intelligently detect outlier requests. This approach is user agent-agnostic and can be turned on or off by your account team.

Cloudflare does not recommend AD for domains that use [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/) or expect large amounts of API traffic. The AD engine immediately gives automated requests a score of one.

### JavaScript detections

Catches headless browsers (browsers controlled by software, with no visible window or human operator) and other automation tools.

The [**JavaScript Detections (JSD)**](https://developers.cloudflare.com/bots/additional-configurations/javascript-detections/) engine identifies headless browsers and other malicious fingerprints. This engine performs a lightweight, invisible JavaScript injection on the client side of any request while honoring our [strict privacy standards ↗](https://www.cloudflare.com/privacypolicy/). We do not collect any personally identifiable information during the process. The JSD engine either blocks, challenges, or passes requests to other engines.

JSD is enabled by default but completely optional. To adjust your settings, open the Bot Management Configuration page from **Security** \> **Bots**.

### Cloudflare service

**Cloudflare Service** is a special bot score source for Enterprise Zero Trust to avoid false positives.

### Not computed

A bot score of 0 means Bot Management did not evaluate the request. This applies to internal Cloudflare service requests and requests that were redirected or handled by another feature (such as [Redirect Rules](https://developers.cloudflare.com/rules/url-forwarding/)) before Bot Management could run. A score of 0 does not indicate the request is safe or human.

### Notes on detection

Cloudflare uses the `__cf_bm` cookie to smooth out the bot score and reduce false positives for actual user sessions.

The Bot Management cookie measures a single user's request pattern and applies it to the machine learning data to generate a reliable bot score for all of that user's requests.

For more details, refer to [Cloudflare Cookies](https://developers.cloudflare.com/fundamentals/reference/policies-compliances/cloudflare-cookies/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/concepts/bot-score/","name":"Bot scores"}}]}
```

---

---
title: Bot tags
description: Tags that explain why Cloudflare assigned a specific bot score to a request.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Bot tags

Bot tags provide more detail about _why_ Cloudflare assigned a [bot score](https://developers.cloudflare.com/bots/concepts/bot-score/) to a request.

Use these tags to learn more about your bot traffic and better inform security settings.

Note

Bot tags are only available to Enterprise customers who have purchased Bot Management.

## Potential values

Once you [enable bot tags](#enable-bot-tags), you can see more information about bot requests, such as whether a request came from a verified bot (like Bing) or a category of verified bot (like SearchEngine).

The following values are **examples** of what may be present in the `BotTags` log field, but not an exhaustive list:

* api
* google
* bing
* googleAds
* googleMedia
* googleImageProxy
* pinterest
* newRelic
* baidu
* apple
* yandex

## Enable bot tags

To enable bot tags, include the `BotTags` log field when using our [Logpush service](https://developers.cloudflare.com/logs/logpush/).

## Limitations

Currently, bot tags are only available in log fields.

Future work will add more values and extend bot tags to other Cloudflare products.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/concepts/bot-tags/","name":"Bot tags"}}]}
```

---

---
title: Signed agents
description: End-user-controlled agents verified through Web Bot Auth cryptographic signatures.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Signed agents

A signed agent is a bot controlled by an end user and verified through [Web Bot Auth](https://developers.cloudflare.com/bots/reference/bot-verification/web-bot-auth/) cryptographic signatures.

You can request for your agent to be added to Cloudflare's bots and agents directory by filling out an [online application ↗](https://dash.cloudflare.com/?to=/:account/configurations/verified-bots) in the Cloudflare dashboard.

Note

A bot cannot be registered as both a verified bot and a signed agent. Review Cloudflare's [verified bots](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/) to determine how to identify your bot.

## Signed agent requirement

For an agent to be recognized, it must meet the following requirements:

1. The agent must follow the [signed agents policy](https://developers.cloudflare.com/bots/concepts/bot/signed-agents/policy/).
2. The bot must be using [Web Bot Auth](https://developers.cloudflare.com/bots/reference/bot-verification/web-bot-auth/).

Once Cloudflare approves a signed agent, it should appear on [Cloudflare Radar's bots and agents directory ↗](https://radar.cloudflare.com/verified-bots).

---

## Verification method

The bot must be verified using [Web Bot Auth](https://developers.cloudflare.com/bots/reference/bot-verification/web-bot-auth/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/concepts/bot/","name":"Bots"}},{"@type":"ListItem","position":5,"item":{"@id":"/bots/concepts/bot/signed-agents/","name":"Signed agents"}}]}
```

---

---
title: Signed agents policy
description: Requirements an agent must meet to be listed as a Cloudflare signed agent.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Signed agents policy

In order to be listed by Cloudflare as a signed agent, your agent must conform to the below requirements. To provide the best possible protection to our customers, this policy may change in the future as we adapt to new bot behaviors.

## Agent policy

### Minimum zones

Service must be made for a widespread use of zones.

#### Example

A bot crawling one site is not valid.

### Agent identification

The user-agent field is optional as it is not required for Web Bot Authentication.

However, if you choose to provide a user-agent, it and the message signature must meet the following requirements:

* Have at least five characters.
* Must not contain special characters.
* Must not include the same user-agent of another verified service.

#### Example

`cloudflare-browser-rendering` is a valid message signature.

### Service purpose

The purpose of the service should be benign or helpful to both the owner of a zone and the users of the service. The service cannot perform any of the following:

* Bot tooling
* Scalpers
* Credential-stuffing
* Directory-traversal scanning
* Excessive data scraping
* DDoS botnets

#### Example

Price scraping direct e-commerce competitors is not a valid use case.

### Public documentation

The agent must have a publicly documented purpose and expected behavior.

---

## Breach of policy

If any of the requirements to validate are breached, a service will be removed from the signed agent list.

The following are examples of breaches of policy:

* The service has vulnerabilities that have not been patched.
* The disclosed purpose of the service does not reflect on the traffic.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/concepts/bot/","name":"Bots"}},{"@type":"ListItem","position":5,"item":{"@id":"/bots/concepts/bot/signed-agents/","name":"Signed agents"}},{"@type":"ListItem","position":6,"item":{"@id":"/bots/concepts/bot/signed-agents/policy/","name":"Signed agents policy"}}]}
```

---

---
title: Verified bots
description: Bots confirmed by Cloudflare as legitimate, such as search engine crawlers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Verified bots

A verified bot is a bot that Cloudflare has confirmed as legitimate, such as search engine crawlers and monitoring services.

You can request for your bot to be added to Cloudflare's bots and agents directory by filling out an [online application ↗](https://dash.cloudflare.com/?to=/:account/configurations/verified-bots) in the Cloudflare dashboard.

Note

A bot cannot be registered as both a verified bot and a signed agent. Review Cloudflare's [signed agents](https://developers.cloudflare.com/bots/concepts/bot/signed-agents/) to determine how to identify your bot.

## Verified bot requirement

For a bot to be verified, it must meet the following requirements:

1. The bot must follow [verified bots policy](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/policy/).
2. The bot must be verified using one of the following verification methods:  
   * [Web Bot Auth](https://developers.cloudflare.com/bots/reference/bot-verification/web-bot-auth/)  
   * [IP validation](https://developers.cloudflare.com/bots/reference/bot-verification/ip-validation/)

Once Cloudflare approves a verified bot, it should appear on [Cloudflare Radar's bots and agents directory ↗](https://radar.cloudflare.com/verified-bots).

---

## Verification methods

The bot must be verified using one of the following validation methods:

* [Web Bot Auth](https://developers.cloudflare.com/bots/reference/bot-verification/web-bot-auth/)
* [IP validation](https://developers.cloudflare.com/bots/reference/bot-verification/ip-validation/)

---

## Categories

You can segment your verified bot traffic by its type and purpose by adding the Verified Bot Categories field `cf.verified_bot_category` as a filter criteria in [WAF Custom rules](https://developers.cloudflare.com/waf/custom-rules/), [Advanced Rate Limiting](https://developers.cloudflare.com/waf/rate-limiting-rules/), and Late Transform rules.

Warning

The Verified Bot Categories field is not compatible with legacy Firewall rules.

Availability

Verified Bot Categories is available on all plans.

Academic research

**String value**: `Academic Research`

**Definition**: Gathers data for scholarly research or academic purposes.

**Example**: Library of Congress, TurnItInBot, Bibliothèque nationale de France

Accessibility

**String value**: `Accessibility`

**Definition**: Scans websites to identify their accessibility.

**Example**: Accessible Web Bot

Advertising or marketing

**String value**: `Advertising & Marketing`

**Definition**: Automates marketing tasks including, but not limited to, ad placement and performance tracking.

**Example**: Google Adsbot

Aggregators

**String value**: `Aggregator`

**Definition**: Collects content from various online sources and consolidates it in one place.

**Example**: Pinterest, Indeed Jobsbot

AI Assistant

**String value**: `AI Assistant`

**Definition**: Automated AI bot driven by user action.

**Example**: Perplexity-User, DuckAssistBot

AI Crawler

**String value**: `AI Crawler`

**Definition**: Crawls websites for content that is used for training AI models.

**Example**: Google Bard, ChatGPT bot

AI Search

**String value**: `AI Search`

**Definition**: Powers AI-driven search experiences.

**Example**: OAI-SearchBot

Archiver

**String value**: `Archiver`

**Definition**: Saves snapshots of websites to preserve digital content for historical records.

**Example**: Internet Archive, CommonCrawl

Feed fetcher

**String value**: `Feed Fetcher`

**Definition**: Retrieves updates from feeds to power readers or other applications.

**Example**: RSS or Podcast feed updaters

Monitoring or analytics

**String value**: `Monitoring & Analytics`

**Definition**: Tracks a website's uptime, performance, and user traffic to gather key monitoring metrics.

**Example**: Uptime Monitors

Page preview

**String value**: `Page Preview`

**Definition**: Generates previews for links shared on social media or in messaging apps.

**Example**: Facebook, Slack, Twitter, or Discord Link Preview tools

Search engine crawler

**String value**: `Search Engine Crawler`

**Definition**: A bot that discovers and indexes web pages for search results.

**Example**: Googlebot, Bingbot, Yandexbot, Baidubot

Search engine optimization

**String value**: `Search Engine Optimization`

**Definition**: Analyzes websites to improve their standing in search engine results pages.

**Example**: Google Lighthouse, GT Metrix, Pingdom, AddThis

Security

**String value**: `Security`

**Definition**: Scans websites to detect security vulnerabilities and potential threats.

**Example**: Vulnerability Scanners, SSL Domain Control Validation (DCV) Check Tools

Social media marketing

**String value**: `Social Media Marketing`

**Definition**: Manages and automates activities on social platforms.

**Example**: Brandwatch

Webhooks

**String value**: `Webhooks`

**Definition**: An automated messenger that sends data from one application to another for specific events.

**Example**: Payment processors, WordPress Integration tools

Other

**String value**: `Other`

**Definition**: A dedicated category for bots that do not fit into the other classifications.

Cloudflare reserves the right to re-assign verified bot categories if the bot's public documentation and observed behavior differ from the category listed in the bot submission form.

---

## Inactive verified bots

Once Cloudflare lists a bot as a verified bot, this entry is cached and may get delisted if no traffic is seen in the Cloudflare network coming from the bot for a defined period of time.

It takes approximately 24 hours for an inactive IP to be removed as a verified bot.

---

### Known issues

The Yandex bot is classified as a Verified Bot, but traffic may occasionally be blocked by a [WAF Managed Rule](https://developers.cloudflare.com/waf/managed-rules/) (such as the rule with ID `...f6cbb163`).

This typically occurs when Yandex updates its source IP address ranges. The new IPs are temporarily unrecognized by the WAF Managed Rules until the updated Verified Bot IP list is fully synchronized across the Cloudflare network.

To restore Yandex traffic, deploy a [WAF exception](https://developers.cloudflare.com/waf/managed-rules/waf-exceptions/) that temporarily skips the managed rule with ID `<RuleID id="2854e3f18ad946049e6d90ccf6cbb163" />` when a request is coming from the **Yandex IP** and the user-agent contains **Yandex**. This ensures that legitimate Yandex traffic bypasses the blocking rule without disabling security features for other traffic.

You can also create a [WAF Custom Rule](https://developers.cloudflare.com/waf/custom-rules/skip/) with the _Skip_ action targeting the managed ruleset that contains the blocking rule. The rule expression should specifically match the request's Yandex IP and User-Agent.

The issue is transient and will resolve automatically once the new Yandex IP addresses are fully propagated to Cloudflare's systems. This propagation typically takes up to 48 hours. If the bot remains blocked after 48 hours, contact [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/).

---

## Availability

Verified bots are excluded by default when [Bot Fight Mode](https://developers.cloudflare.com/bots/get-started/bot-fight-mode/) is enabled to block definite bots.

[Super Bot Fight Mode](https://developers.cloudflare.com/bots/get-started/super-bot-fight-mode/) and [Enterprise Bot Management](https://developers.cloudflare.com/bots/get-started/bot-management/) customers have the option to block or allow verified bots.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/concepts/bot/","name":"Bots"}},{"@type":"ListItem","position":5,"item":{"@id":"/bots/concepts/bot/verified-bots/","name":"Verified bots"}}]}
```

---

---
title: Verified bots policy
description: Requirements a bot must meet to be listed as a Cloudflare verified bot.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Verified bots policy

In order to be listed by Cloudflare as a [verified bot](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/), your bot must conform to the below requirements. To provide the best possible protection to our customers, this policy may change in the future as we adapt to new bot behaviors.

## Bot policy

### Minimum traffic

A bot or proxy must have a minimum amount of traffic for Cloudflare to be able to find it in the sampled data. The minimum traffic should have more than 1,000 requests per day across multiple domains.

Note

Minimum traffic is not a requirement if you are using [Web Bot Auth](https://developers.cloudflare.com/bots/reference/bot-verification/web-bot-auth/) as an authentication method.

### Minimum zones

Service must be made for a widespread use of zones.

#### Example

A bot crawling one site is not valid.

### Bot identification

The user-agent or message signature with the following requirements:

* Have at least five characters.
* Must not contain special characters.
* Must not include the same user-agent of another verified service.

#### Example

`GoogleBot/1.0` is a valid user-agent.

### Domain owner consent

Domains should only be crawled with the explicit or implicit consent of the zone's owner or terms of use. Search engines crawlers must read the `robots.txt` to exclude paths to crawl from the owner.

#### Example

A tool trying to scalp inventories from different websites might be breaking terms of use while a search engine bot indexing websites but complying with `robots.txt` is a valid service.

### Service purpose

The purpose of the service should be benign or helpful to both the owner of a zone and the users of the service. The service cannot perform any of the following:

* Bot tooling
* Scalpers
* Credential-stuffing
* Directory-traversal scanning
* Excessive data scraping
* DDoS botnets

#### Example

Price scraping direct e-commerce competitors is not a valid use case.

### Crawling etiquette

The crawling etiquette should check `robots.txt` if crawling the whole website, and it should not attempt to crawl sensitive paths.

#### Example

If a search engine crawler skips `robots.txt`, it will be rejected.

### Public documentation

The bot must have publicly documented expected behavior or user-agent format.

---

## Breach of Policy

If any of the requirements to validate are breached, a service will be removed from the global allowlist.

The following are examples of breaches of policy:

* Adding a set of IPs that are not solely used by verified service.
* The service IPs are breached by an attacker.
* The service has vulnerabilities that have not been patched.
* A block of IPs not briefed on onboarding is added to the list.
* The disclosed purpose of the service does not reflect on the traffic.
* An AI Crawler that does not respect the crawl-delay directive in robots.txt.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/concepts/bot/","name":"Bots"}},{"@type":"ListItem","position":5,"item":{"@id":"/bots/concepts/bot/verified-bots/","name":"Verified bots"}},{"@type":"ListItem","position":6,"item":{"@id":"/bots/concepts/bot/verified-bots/policy/","name":"Verified bots policy"}}]}
```

---

---
title: Bot Feedback Loop
description: Submit feedback to improve bot detection accuracy for your domain.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Bot Feedback Loop

The Bot Feedback Loop allows you to report requests that Bot Management [scored](https://developers.cloudflare.com/bots/concepts/bot-score/) incorrectly. When you submit a false negative or false positive report, Cloudflare analyzes the data and uses it to train the next machine learning model.

## Availability

Bot Feedback Loop is available for Enterprise Bot Management customers. Visit [Plans](https://developers.cloudflare.com/bots/plans/) for more information.

## False Positive

A false positive can happen if Cloudflare scores a request from a person using a browser, mobile application or desktop application in the _automated_ or _likely automated_ range.

## False Negative

If Cloudflare is unable to detect a portion of automated traffic on your site, submitting a False Negative report will help us catch it in the future.

### Subtypes

| Subtype                | Definition                                                                                                                                                                                                |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Account Creation Abuse | The automated creation of many new accounts in order to gain access to site resources.                                                                                                                    |
| Ad Fraud               | Fraudulent increase in the number of times an advertisement is clicked on or displayed.                                                                                                                   |
| Credit Card Abuse      | Attempts to repeatedly validate many credit card numbers or the same credit card number with different validation details.                                                                                |
| Cashing Out            | Abusing the target Internet application to obtain valuable goods.                                                                                                                                         |
| Login Abuse            | Attempts to gain access to a password protected portion of an Internet application using many different combinations of usernames and passwords.                                                          |
| Inventory Abuse        | Automated abuse related to purchasing limited stock inventory or holding inventory to prevent others from making transactions.                                                                            |
| Denial of Service      | Automated requests with the intent of exhausting server resources to prevent the Internet application from functioning.                                                                                   |
| Expediting             | Automating the use of an Internet application to make transactions faster than a human visitor to gain unfair advantage.                                                                                  |
| Fuzzing                | Finding implementation bugs through the use of malformed data injection in an automated fashion.                                                                                                          |
| Scraping               | Automated retrieval of valuable or proprietary information from an Internet application.                                                                                                                  |
| Spamming               | The abuse of content forms to send spam.                                                                                                                                                                  |
| Token Cracking         | Identification of valid token codes providing some form of user benefit within the application.                                                                                                           |
| Vulnerability Scanning | Systematic enumeration and examination of identifiable, guessable and unknown content locations, paths, file names, parameters, to find weaknesses and points where a security vulnerability might exist. |

## Submit a report

* [  New dashboard ](#tab-panel-6692)
* [ Old dashboard ](#tab-panel-6693)

1. In the Cloudflare dashboard, go to the **Security Analytics** page.  
[ Go to **Analytics** ](https://dash.cloudflare.com/?to=/:account/:zone/security/analytics)
2. Apply one or more filters.
3. Under **Request activity**, filter by **Bot analysis**.
4. Select **Report incorrect data** and fill out the form.
5. Select **Submit**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Bots**.
3. Apply one or more bot score filters.
4. Select **Report incorrect data** and fill out the form.
5. Select **Submit**.

## Via the API

### Create a feedback report

Terminal window

```

curl 'https://api.cloudflare.com/client/v4/zones/{zone_id}/bot_management/feedback' \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data '{

  "type": "false_positive",

  "description": "Legitimate customers having low score",

  "expression": "(cf.bot_management.score le 46 and ip.src.asnum eq 132892 and http.host eq \"api-discovery.theburritobot.com\" and cf.bot_management.ja3_hash eq \"3fed133de60c35724739b913924b6c24\")",

  "first_request_seen_at": "2022-08-01T00:00:00Z",

  "last_request_seen_at": "2022-08-10T00:00:00Z",

  "requests": 100,

  "requests_by_score": {

    "1": 50,

    "10": 50

  },

  "requests_by_score_src": {

    "heuristics": 25,

    "machine_learning": 75

  },

  "requests_by_attribute": {

    "topIPs": [

      {

        "metric": "10.75.34.1",

        "requests": 100

      }

    ],

    "topUserAgents": [

      {

        "metric": "curl/7.68.0",

        "requests": 100

      }

    ]

  }

}'


```

### List feedback reports

Terminal window

```

curl 'https://api.cloudflare.com/client/v4/zones/{zone_id}/bot_management/feedback' \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>"


```

```

[

  {

    "created_at": "2022-08-19T00:05:24.749712Z",

    "type": "false_positive",

    "description": "Legitimate customers having low score",

    "expression": "(cf.bot_management.score le 46 and ip.src.asnum eq 132892 and http.host eq \"api-discovery.theburritobot.com\" and cf.bot_management.ja3_hash eq \"3fed133de60c35724739b913924b6c24\")",

    "first_request_seen_at": "2022-08-01T00:00:00Z",

    "last_request_seen_at": "2022-08-10T00:00:00Z",

    "requests": 100,

    "requests_by_score": {

      "1": 50,

      "10": 50

    },

    "requests_by_score_src": {

      "heuristics": 25,

      "machine_learning": 75

    },

    "requests_by_attribute": {

      "topIPs": [

        {

          "metric": "10.75.34.1",

          "requests": 100

        }

      ],

      "topUserAgents": [

        {

          "metric": "curl/7.68.0",

          "requests": 100

        }

      ]

    }

  }

]


```

## API Fields

| Field                    | Type    | Description                                                                 | Value Example                                                                                                                                                         |
| ------------------------ | ------- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type                     | string  | The feedback report type.                                                   | false\_positive                                                                                                                                                       |
| description              | string  | The feedback report description with more details on the issue.             | Legitimate customers having low scores.                                                                                                                               |
| expression               | string  | The wirefilter expression matching reported requests.                       | (cf.bot\_management.score le 46 and ip.src.asnum eq 132892 and http.host eq "app.example.com" and cf.bot\_management.ja3\_hash eq "3fed133de60c35724739b913924b6c24") |
| first\_request\_seen\_at | string  | The time range start when the first request has been seen, RFC 3339 format. | 2022-08-01T00:00:00Z                                                                                                                                                  |
| last\_request\_seen\_at  | string  | The time range end when the last request has been seen, RFC 3339 format.    | 2022-08-10T00:00:00Z                                                                                                                                                  |
| requests                 | integer | The total number of reported requests.                                      | 100                                                                                                                                                                   |
| requests\_by\_score      | object  | The requests breakdown by score.                                            | See example below.                                                                                                                                                    |
| requests\_by\_score\_src | object  | Requests breakdown by score source.                                         | See example below.                                                                                                                                                    |
| requests\_by\_attribute  | object  | Requests breakdown by attribute (optional).                                 | See example below.                                                                                                                                                    |

`requests_by_score`

```

{

  "1": 50,

  "10": 50

}


```

`requests_by_score_src`

```

{

  "machine_learning": 75,

  "heuristics": 25

}


```

`requests_by_attribute`

```

{

  "topIPs": [

    {

      "metric": "10.75.34.1"

      "requests": 100

    }

  ],

  "topUserAgents": [

    {

      "metric": "curl/7.68.0",

      "requests": 100

    }

  ]

}


```

### Expression fields

| Field                        | Type    | Description                                                                                                                                                                 |
| ---------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cf.bot\_management.ja3\_hash | string  | This provides an SSL/TLS fingerprint to help you identify potential bot requests.                                                                                           |
| cf.bot\_management.score     | integer | This represents the likelihood that a request originates from a bot using a score from 1-99.                                                                                |
| http.host                    | string  | This represents the hostname used in the full request URI.                                                                                                                  |
| http.request.uri.path        | string  | This represents the URI path of the request.                                                                                                                                |
| http.user\_agent             | string  | This represents the HTTP user agent which is a request header that contains a characteristic string to allow identification of the client operating system and web browser. |
| ip.src.asnum                 | integer | This represents the 16- or 32-bit integer representing the Autonomous System (AS) number associated with client IP address.                                                 |
| ip.src.country               | string  | This represents the 2-letter country code in ISO 3166-1 Alpha 2 format.                                                                                                     |
| ip.src                       | string  | The source address of the IP.                                                                                                                                               |

## Recommendations when submitting a report

When you submit a report, use the filters available in the Bot Analytics dashboard to ensure that your report includes only the traffic that received an incorrect score. In addition to filtering by a score (required), you may want to filter by user-agent, IP, ASN or JA3 to more precisely highlight the section of traffic that was scored incorrectly.

If you are not certain if some traffic received an incorrect score, keep this traffic in the report.

We appreciate any comments you wish to leave in the description field that might help our team better understand these requests in the context of typical traffic to your domain.

## Recommendations after submitting a false positive

Note

The instructions below apply to Enterprise subscription with Bot Management only.

After submitting a false positive, you can explicitly allow the traffic if you are confident that this traffic source cannot be used for abuse in the future. To allow traffic, you can create a WAF custom rule with a [Skip the remaining custom rules](https://developers.cloudflare.com/waf/custom-rules/skip/options/#skip-the-remaining-custom-rules-current-ruleset) action that matches the characteristics of your false positive report. We recommend any skip rule that you create uses the most narrow possible scope, including restricting the request methods and URIs that the expected traffic has access to, to limit potential abuse.

* Allowing a **[JA3/JA4 fingerprint](https://developers.cloudflare.com/bots/additional-configurations/ja3-ja4-fingerprint/)**: If you want to allow access to a stable software client that does not come from a dedicated IP, you can do so by looking up the JA3 fingerprint(s) used by that client in the Bot Analytics dashboard, and creating a WAF custom rule to allow traffic based on that JA3 fingerprint. JA3 fingerprints will only match a client’s TLS library, so be cautious in looking for both overlap with other clients and with variation based on the operating system.  
    
Cloudflare does not recommend relying on JA3 rules for mobile applications that may be abused. If you have questions about how to securely allow traffic from your mobile application, please contact your account team.

Note

The instructions below apply to Enterprise subscription with Bot Management, Bot Fight Mode and Super Bot Fight Mode.

* Allowing an **IP address**: Only use an IP address to allow traffic if the IP is a dedicated resource that belongs only to the traffic source you wish to allow.  
If the traffic you want to allow shares an IP with other traffic sources, or if the IP changes frequently, consider an alternative to allowing by IP address.

## Recommendations after submitting a false negative

After submitting a false negative report, you can explicitly block or rate-limit the incorrectly scored traffic using a combination of characteristics such as IP address, JA3 fingerprint, ASN, and user-agent. Before blocking or rate-limiting based on JA3 fingerprint, please use Bot Analytics to confirm that fingerprint is not being used by legitimate traffic sources.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/concepts/feedback-loop/","name":"Bot Feedback Loop"}}]}
```

---

---
title: Bot Fight Mode
description: Turn on Bot Fight Mode to challenge requests matching bot patterns on Free plans.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Bot Fight Mode

Bot Fight Mode is a simple, free product that helps detect and mitigate bot traffic on your domain. When enabled, the product:

* Identifies traffic matching patterns of known bots
* Issues computationally expensive challenges that force the requesting client to perform CPU-intensive calculations, increasing the cost for bots to send automated requests
* Notifies [Bandwidth Alliance ↗](https://cloudflare.com/bandwidth-alliance/) partners (if applicable) to disable bots

## Considerations

Bot Fight Mode and Super Bot Fight Mode use the same underlying technology that powers our [Bot Management ↗](https://www.cloudflare.com/products/bot-management/) product. Specifically, these products:

* Protect entire domains without endpoint restrictions
* Cannot be customized, adjusted, or reconfigured via WAF custom rules

Although these products are designed to fight malicious actors on the Internet, they may challenge API or mobile app traffic. For more granular control, upgrade to [Bot Management for Enterprise](https://developers.cloudflare.com/bots/plans/bm-subscription/).

## Interaction with other app security features

If you are using several app security features like custom rules, Managed Rules, and Bot Fight Mode, it is important to understand how these features interact and the order in which they execute. Refer to [Security features interoperability](https://developers.cloudflare.com/waf/feature-interoperability/) for more information.

---

## Enable Bot Fight Mode

To start using Bot Fight Mode:

* [  New dashboard ](#tab-panel-6696)
* [ Old dashboard ](#tab-panel-6697)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **Bot traffic**.
3. Go to **Bot fight mode**.
4. Turn **Bot fight mode** on.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/login), and select your account and domain.
2. Go to **Security** \> **Bots**.
3. For **Bot Fight Mode**, select **On**.

Note

If you are upgrading from Bot Fight Mode to Super Bot Fight Mode, you must disable Bot Fight Mode in your Bot settings.

* Old dashboard: **Security** \> **Bots**, and select **Configure Bot Fight Mode**.
* New dashboard: **Security** \> **Settings**. Filter by **Bot traffic** and turn **Bot fight mode** off.

---

## Disable Bot Fight Mode

If you find that **Bot Fight Mode** is causing problems with your application traffic, you may want to disable it.

To disable Bot Fight Mode:

* [  New dashboard ](#tab-panel-6694)
* [ Old dashboard ](#tab-panel-6695)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **Bot traffic**.
3. Go to **Bot Fight Mode**.
4. Turn **Bot Fight Mode** off.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/login), and select your account and domain.
2. Go to **Security** \> **Bots**.
3. For **Bot Fight Mode**, select **Off**.

---

## Block AI bots

Refer to [Block AI bots](https://developers.cloudflare.com/bots/additional-configurations/block-ai-bots/).

Note

You can view blocked AI bot traffic via [Security Analytics](https://developers.cloudflare.com/waf/analytics/security-analytics/).

---

## Visibility

You can see bot-related actions by going to **Security** \> **Events**. Any requests challenged by this product will be labeled **Bot Fight Mode** in the **Service** field. This allows you to observe, analyze, and follow trends in your bot traffic over time.

---

## Limitations

### Rules

You cannot bypass or skip Bot Fight Mode using WAF custom rules or Page Rules. This is because Bot Fight Mode does not run on the [Ruleset Engine](https://developers.cloudflare.com/ruleset-engine/) — it operates in a separate evaluation pipeline where _Skip_, _Bypass_, and _Allow_ actions have no effect.

If you need to create exceptions for specific traffic (for example, your own API clients or monitoring tools), use [Super Bot Fight Mode](https://developers.cloudflare.com/bots/get-started/super-bot-fight-mode/) instead. Super Bot Fight Mode runs on the Ruleset Engine and supports Skip rules.

Bot Fight Mode can still trigger if you have [IP Access rules](https://developers.cloudflare.com/waf/tools/ip-access-rules/), but it will not trigger if an IP Access rule matches the request first.

### JavaScript Detections

For Bot Fight Mode customers, [JavaScript Detections](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/javascript-detections/) is automatically enabled and cannot be disabled.

If you have a Content Security Policy (CSP), you need to take additional steps to implement JavaScript Detections:

* Ensure that anything under `/cdn-cgi/challenge-platform/` is allowed. Your CSP should allow scripts served from your origin domain (`script-src self`).
* For `nonce` script tags:  
   * If your CSP uses a `nonce` for script tags, Cloudflare will add these nonces to the scripts it injects by parsing your CSP response header.  
   * If your CSP does not use `nonce` for script tags and **JavaScript Detections** is enabled, you may see a console error such as `Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-b123b8a70+4jEj+d6gWI9U6IilUJIrlnRJbRR/uQl2Jc='), or a nonce ('nonce-...') is required to enable inline execution.` We highly discourage the use of `unsafe-inline` and instead recommend the use CSP `nonces` in script tags which we parse and support in our CDN.

Warning

JavaScript Detections is not supported with `nonce` set via `<meta>` tags.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/get-started/","name":"Get started with Cloudflare bot solutions"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/get-started/bot-fight-mode/","name":"Bot Fight Mode"}}]}
```

---

---
title: Bot Management
description: Configure Bot Management for Enterprise to identify and act on automated traffic.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Bot Management

Bot Management for Enterprise is a paid add-on that provides sophisticated bot protection for your domain. Customers can identify automated traffic, take appropriate action, and view detailed analytics within the dashboard.

This Enterprise product provides the most flexibility to customers by:

* Generating a [bot score](https://developers.cloudflare.com/bots/concepts/bot-score/) of 1-99 for every request. Scores below 30 are commonly associated with bot traffic. This lets you write targeted rules instead of applying blanket actions to all detected bots.
* Allowing customers to take action on this score with [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/) or [Workers](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties). For example, you can challenge low-scoring requests on your login page while allowing them on your public blog.
* Allowing customers to view this score in Bot Analytics or Logs, so you can analyze bot traffic patterns and tune your rules over time.

---

## Enable Bot Management for Enterprise

Bot Management is automatically enabled for Enterprise zones entitled with the add-on.

* [  New dashboard ](#tab-panel-6698)
* [ Old dashboard ](#tab-panel-6699)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **Bot traffic**.
3. Go to **Bot management**.
4. Turn **Bot management** on.
5. Choose how your domain should respond to various types of traffic by selecting the associated edit icon.  
   * For more details on verified bots, refer to [Verified Bots](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/).  
   * For more details on supported file types, refer to [Static resource protection](https://developers.cloudflare.com/bots/additional-configurations/static-resources/).  
   * For more details on invisible code injection, refer to [JavaScript detections](https://developers.cloudflare.com/bots/additional-configurations/javascript-detections/).  
   * For more details on WordPress optimization, refer to [Super Bot Fight Mode for WordPress](https://developers.cloudflare.com/bots/troubleshooting/wordpress-loopback-issue/).

To enable a [Bot Management ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/bots) trial on Enterprise zones without the Bot Management add-on entitled:

1. Log in to your [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Bots**.
3. Select **Add Bot Management**.

Note

If you are not seeing Bot Management enabled on your zone or if you still see **Add Bot Management** on the Cloudflare dashboard, contact your account team for the proper entitlements.

---

## Setup

Cloudflare recommends that you deploy the following basic settings and customize them according to the traffic in your zone.

### Enable the latest Machine Learning version

Cloudflare encourages Enterprise customers to enable auto-updates to its Machine Learning models to get the newest bot detection models as they are released.

To enable auto-updates:

* [  New dashboard ](#tab-panel-6700)
* [ Old dashboard ](#tab-panel-6701)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **Bot traffic**.
3. Go to **Bot Management**.
4. Under **Configurations**, select the edit icon for **Auto-updates to the Machine Learning Model** and turn it on.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Bots**.
3. Select **Configure Bot Management**.
4. Enable **Auto-updates to the Machine Learning Model**.

### Block AI Bots

Refer to [Block AI bots](https://developers.cloudflare.com/bots/additional-configurations/block-ai-bots/).

Note

You can view blocked AI bot traffic via [Security Analytics](https://developers.cloudflare.com/waf/analytics/security-analytics/).

### Deploy custom rule templates

The **Definitely Automated** and **Likely Automated** toggles you configured in the previous step already provide baseline protection against automated traffic.

If you need additional control, such as path-specific protection, custom score thresholds, or combining bot score with other fields, Cloudflare provides [rule templates ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules?template=bot%5Ftraffic) to get started.

Note

Custom rules created from these templates execute before the managed rules configured in **Security Settings**. For more details on this execution order, refer to [Security features interoperability](https://developers.cloudflare.com/waf/feature-interoperability/).

These templates use wirefilter expression syntax. In these expressions, `eq` means equals, `le` means less than or equal to, `ge` means greater than or equal to, and `not` excludes matching traffic.

* [Definite Bots template ↗](https://dash.cloudflare.com/?to=/:account/:zone:/security/security-rules/custom-rules/create?template=Definitely%20Bots): Targets malicious bot traffic while ignoring verified bots and routes delivering static content.  
```  
(cf.bot_management.score eq 1 and not cf.bot_management.verified_bot and not cf.bot_management.static_resource)  
```
* [Likely Bots template ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules/custom-rules/create?template=Likely%20Bots): Targets traffic likely to be malicious bots while ignoring verified bots and routes with static content. It may contain a small amount of non-bot traffic.  
```  
(cf.bot_management.score ge 2 and cf.bot_management.score le 29 and not cf.bot_management.verified_bot and not cf.bot_management.static_resource)  
```
* (Optional) [JavaScript detections template ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules/custom-rules/create?template=JavaScript%20Verified%20URLs): You must first enable JavaScript Detections from Security Settings, then set up a [managed challenge](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/#managed-challenge). Make sure to add a method and URI path. JavaScript detections improves security for URLs that should only expect JavaScript-enabled clients.  
```  
(not cf.bot_management.js_detection.passed and http.request.method eq "" and http.request.uri.path in {""})  
```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/get-started/","name":"Get started with Cloudflare bot solutions"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/get-started/bot-management/","name":"Bot Management"}}]}
```

---

---
title: Super Bot Fight Mode
description: Configure Super Bot Fight Mode to challenge or block bots on Pro, Business, and Enterprise plans.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Super Bot Fight Mode

Super Bot Fight Mode is included in your Pro, Business, or Enterprise subscription. Compared to [Bot Fight Mode](https://developers.cloudflare.com/bots/get-started/bot-fight-mode/), Super Bot Fight Mode adds configurable actions per bot category, bot analytics, and the ability to create exceptions using [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/). When enabled, the product:

* Identifies traffic matching patterns of known bots
* Can challenge or block bots
* Offers protection for static resources
* Provides limited analytics to help you understand bot traffic

Accounts with an Enterprise subscription but not the [Bot Management add-on](https://developers.cloudflare.com/bots/get-started/bot-management/) will have Super Bot Fight Mode for Business.

## Considerations

Bot Fight Mode and Super Bot Fight Mode use the same underlying technology that powers our [Bot Management ↗](https://www.cloudflare.com/products/bot-management/) product. Specifically, these products:

* Protect entire domains without endpoint restrictions
* Cannot be customized, adjusted, or reconfigured via WAF custom rules

Although these products are designed to fight malicious actors on the Internet, they may challenge API or mobile app traffic. For more granular control, upgrade to [Bot Management for Enterprise](https://developers.cloudflare.com/bots/plans/bm-subscription/).

### Interaction with other app security features

If you are using several app security features like custom rules, Managed Rules, and Super Bot Fight Mode, it is important to understand how these features interact and the order in which they execute. Refer to [Security features interoperability](https://developers.cloudflare.com/waf/feature-interoperability/) for more information.

### Configure exceptions to Super Bot Fight Mode

[Custom rules](https://developers.cloudflare.com/waf/custom-rules/) are executed before Super Bot Fight Mode. To configure exceptions to Super Bot Fight Mode, create a custom rule with the [_Skip_ action](https://developers.cloudflare.com/waf/custom-rules/skip/). The _Skip_ action allows the request to bypass the Super Bot Fight Mode phase without terminating the request, enabling it to continue through the rest of the security stack.

## Enable Super Bot Fight Mode

Note

If you are upgrading from Bot Fight Mode to Super Bot Fight Mode, you must disable Bot Fight Mode in your Bot settings.

* Old dashboard: **Security** \> **Bots**, and select **Configure Bot Fight Mode**.
* New dashboard: **Security** \> **Settings**. Filter by **Bot traffic** and turn **Bot fight mode** off.

To start using Super Bot Fight Mode:

* [  New dashboard ](#tab-panel-6704)
* [ Old dashboard ](#tab-panel-6705)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **Bot traffic**.
3. Go to **Super Bot fight mode**.
4. Turn **Super Bot fight mode** on.
5. Choose how your domain should respond to various types of traffic by selecting the associated edit icon:  
   * For more details on verified bots, refer to [Verified Bots](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/).  
   * For more details on supported file types, refer to [Static resource protection](https://developers.cloudflare.com/bots/additional-configurations/static-resources/).  
   * For more details on invisible code injection, refer to [JavaScript detections](https://developers.cloudflare.com/bots/additional-configurations/javascript-detections/).  
   * For more details on WordPress optimization, refer to [Super Bot Fight Mode for WordPress](https://developers.cloudflare.com/bots/troubleshooting/wordpress-loopback-issue/).

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/login), and select your account and domain.
2. Go to **Security** \> **Bots**.
3. Select **Configure Super Bot Fight Mode**.
4. Choose how your domain should respond to various types of traffic:  
   * For more details on verified bots, refer to [Verified Bots](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/).  
   * For more details on supported file types, refer to [Static resource protection](https://developers.cloudflare.com/bots/additional-configurations/static-resources/).  
   * For more details on invisible code injection, refer to [JavaScript detections](https://developers.cloudflare.com/bots/additional-configurations/javascript-detections/).  
   * For more details on WordPress optimization, refer to [Super Bot Fight Mode for WordPress](https://developers.cloudflare.com/bots/troubleshooting/wordpress-loopback-issue/).

Warning

If your organization also uses [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/), keep **Definitely Automated** set to **Allow**. Otherwise, Super Bot Fight Mode may block tunnel connections, causing failures with a `websocket: bad handshake` error.

In parts of your site where you want bot traffic, you can use the [_Skip_ action](https://developers.cloudflare.com/waf/custom-rules/skip/) in [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/) to specify where Super Bot Fight Mode should not run.

You can use the [Rules language](https://developers.cloudflare.com/ruleset-engine/rules-language/) and its [operators](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/) and [fields](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/) in custom rules to configure a scoped rule for approved automated traffic in Super Bot Fight Mode.

---

## Disable Super Bot Fight Mode

If you find that **Super Bot Fight Mode** is causing problems with your application traffic, you may want to disable it.

To disable Super Bot Fight Mode:

* [  New dashboard ](#tab-panel-6702)
* [ Old dashboard ](#tab-panel-6703)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **Bot traffic**.
3. Go to **Super Bot Fight Mode**.
4. For all bot groupings (**Definitely automated traffic**, **Likely automated traffic**, and **Verified bots**), set the value to **Allow**.
5. For all other options (**Static resource protection**, **JavaScript detections**, and **Optimize for WordPress**), select the edit icon and ensure they are off.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/login), and select your account and domain.
2. Go to **Security** \> **Bots**.
3. Select **Configure Super Bot Fight Mode**.
4. For all bot groupings (**Definitely automated traffic**, **Likely automated traffic**, and **Verified bots**), set the value to **Allow**.
5. For all other options (**Static resource protection**, **JavaScript detections**, and **Optimize for WordPress**), select the edit icon and ensure they are off.

In parts of your site where you want bot traffic, you can use the [_Skip_ action](https://developers.cloudflare.com/waf/custom-rules/skip/) in [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/) to specify where Super Bot Fight Mode should not run.

You can use the [Rules language](https://developers.cloudflare.com/ruleset-engine/rules-language/) and its [operators](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/) and [fields](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/) in custom rules to configure a scoped rule for approved automated traffic in Super Bot Fight Mode.

---

## Block AI bots

Refer to [Block AI bots](https://developers.cloudflare.com/bots/additional-configurations/block-ai-bots/).

Note

You can view blocked AI bot traffic via [Security Analytics](https://developers.cloudflare.com/waf/analytics/security-analytics/).

---

## Analytics

### Bot Report

Use the **Bot Report** to monitor bot traffic for the past 24 hours.

To access the **Bot Report**, go to **Security** \> **Bots**. If you see a double-digit percentage of automated traffic, you may want to upgrade to [Bot Management](https://developers.cloudflare.com/bots/plans/bm-subscription/) to save money on origin costs and protect your domain from large-scale attacks.

![Example traffic distribution as part of a bot report](https://developers.cloudflare.com/_astro/bot-report-pro.BU1S3xco_ZvNVOm.webp) 

### Security events

You can see bot-related actions by going to **Security** \> **Events**. Any requests challenged by this product will be labeled **Super Bot Fight Mode** in the **Service** field. This allows you to observe, analyze, and follow trends in your bot traffic over time.

---

## Ruleset Engine

Super Bot Fight Mode rules run after WAF custom rules in the request evaluation pipeline. Specifically, Super Bot Fight Mode runs during the `http_request_sbfm` phase of the [Ruleset Engine](https://developers.cloudflare.com/ruleset-engine/about/phases/).

Change notice for Super Bot Fight Mode rulesets

Updating Super Bot Fight Mode rules via the Rulesets API is no longer supported and may cause unexpected behavior if you do so.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/get-started/","name":"Get started with Cloudflare bot solutions"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/get-started/super-bot-fight-mode/","name":"Super Bot Fight Mode"}}]}
```

---

---
title: Bot Detection Alerts
description: Set up notifications for spikes in bot traffic on your domain.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Bot Detection Alerts

Bot alerts inform you when Cloudflare detects spikes in your traffic with any of the following characteristics:

* A global spike in traffic that has a bot score of less than 30.
* An increase in traffic on available dimensions in [Set up a bot detection alert](#set-up-a-bot-detection-alert).
* Filters of your choosing in [Set up a bot detection alert](#set-up-a-bot-detection-alert).

---

## Alert types

Bot Detection Alert

**Who is it for?**

Enterprise customers who want to be notified when Cloudflare detects a spike in bot traffic on their zones.

**Other options / filters**

None.

**Included with**

Accounts with at least one Enterprise zone.

**What should you do if you receive one?**

Select the [Security Analytics](https://developers.cloudflare.com/waf/analytics/security-analytics/) link enclosed in the alert message. Contact support if additional advice is needed on how to investigate the attack further.

**Additional information**

After an alert is created on the dashboard, it may take up to 30 minutes before sufficient data is available to begin detecting traffic anomalies. Verified bot traffic is excluded from bot alerts.

Custom Bot Detection Alert

**Who is it for?**

Enterprise customers who want to be notified when Cloudflare detects a spike in bot traffic on their zones.

**Other options / filters**

Refer to the [alert logic](https://developers.cloudflare.com/bots/reference/alerts/#alert-logic) for more information on additional filters or groupings.

**Included with**

Accounts with at least one Enterprise zone.

**What should you do if you receive one?**

Select the [Security Analytics](https://developers.cloudflare.com/waf/analytics/security-analytics/) link enclosed in the alert message. Contact support if additional advice is needed on how to investigate the attack further.

**Additional information**

After an alert is created on the dashboard, it may take up to 30 minutes before sufficient data is available to begin detecting traffic anomalies. Verified bot traffic is excluded from both basic and advanced bot alerts.

Alerts with grouping could cause potential noise if you set them up for a high-traffic zone. Grouping alerts function as if you set up separate policies with a filter for each value. Alerts may trigger multiple values in the same group as long as the traffic for each value reaches the threshold of 200.

### Set up a bot detection alert

To receive Bot alerts, you must [configure a notification](https://developers.cloudflare.com/notifications/get-started/). Notifications help you stay up to date with your Cloudflare account through email, PagerDuty, or webhooks, depending on your Cloudflare plan.

1. In the Cloudflare dashboard, go to the **Notifications** page.  
[ Go to **Notifications** ](https://dash.cloudflare.com/?to=/:account/notifications)
2. Select **Add**.
3. Select **Bot Management** from the Product list.
4. Choose one of the available bot detection alerts (depending on whether you want to set up custom filters and/or grouping):  
   * Bot Detection Alert  
   * Custom Bot Detection Alert
5. Enter a notification name and (optionally) a description.
6. Select the domain(s) to monitor for this alert.
7. Configure a delivery method for the notification. The available delivery methods depend on your Cloudflare plan. For more information, refer to [Cloudflare Notifications](https://developers.cloudflare.com/notifications/).
8. If you are creating a notification for Custom Bot Detection Alert, define the parameters that will filter the notifications you will receive.
9. Select **Save**.

---

## Alert logic

The Bot Detection Alert notifies you when Cloudflare detects an abnormal spike to your zone where the [Z-score ↗](https://blog.cloudflare.com/introducing-thresholds-in-security-event-alerting-a-z-score-love-story/) exceeds 3.5 and bot requests exceed 200 per 5 minutes (bot score below 30). A Z-score measures how far a value deviates from the average, so a Z-score above 3.5 indicates a statistically unusual traffic spike.

The Z-score is calculated using a six-hour baseline window and a five-minute observation window.

Bot Detection Alerts are delivered with Cloudflare’s Notifications system via email, webhook, or Pager Duty.

You will not receive duplicate alerts within the same one-hour time frame, except in rare cases where different alert values simultaneously trigger alerts.

In addition to the information above, Custom Bot Detection Alerts allow you to include or exclude certain conditions:

* User-agent
* Hostname
* URI Path
* IP Source Address
* Autonomous System Number (AS Num)
* JA3 Fingerprint
* JA4 Fingerprint
* Bot Detection IDs

You can also choose to group by the following dimensions so that they can be alerted of volumetric anomalies based on:

* JA4 Fingerprint (removes the filter of bot score < 30)
* AS Num
* Bot Detection IDs

Note

Bot Detection Alerts exclude [verified bots](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/reference/alerts/","name":"Bot Detection Alerts"}}]}
```

---

---
title: Bot Management variables
description: Ruleset Engine fields and Workers variables available for bot detection rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Bot Management variables

## Ruleset Engine fields

Bot Management provides access to several [new variables](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/?field-category=Bots) within the expression builder of Ruleset Engine-based products such as [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/).

* **Bot Score** (`cf.bot_management.score`): An integer between 1-99 that indicates [Cloudflare's level of certainty](https://developers.cloudflare.com/bots/concepts/bot-score/) that a request comes from a bot.
* **Verified Bot** (`cf.bot_management.verified_bot`): A boolean value that indicates whether a request originates from a Cloudflare allowed bot.  
Cloudflare maintains a large allowlist of good, automated bots (such as Google Search Engine and Pingdom) that perform beneficial tasks. Cloudflare identifies and verifies these bots primarily through reverse DNS validation, ensuring the source IP matches the requesting service.  
We also use additional validation methods, including checking ASN blocks and public lists. If these methods are unavailable, Cloudflare utilizes internal data and machine learning to identify and verify legitimate IP addresses from good bots. Most customers choose to [allow this traffic](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.bot%5Fmanagement.verified%5Fbot/).
* **Serves Static Resource** (`cf.bot_management.static_resource`): An identifier that matches [file extensions](https://developers.cloudflare.com/bots/additional-configurations/static-resources/) for many types of static resources. Use this variable if you send emails that retrieve static images.
* **ja3Hash** (`cf.bot_management.ja3_hash`) and **ja4** (`cf.bot_management.ja4`): A [**JA3/JA4 fingerprint**](https://developers.cloudflare.com/bots/additional-configurations/ja3-ja4-fingerprint/) helps you profile specific SSL/TLS clients across different destination IPs, Ports, and X509 certificates.
* **Bot Detection IDs** (`cf.bot_management.detection_ids`): List of IDs that correlate to the Bot Management heuristic detections made on a request (you can have multiple heuristic detections on the same request).
* **Signed Agent** (`cf.bot_management.signed_agent`): A boolean value that indicates whether the request originated from a known [signed agent](https://developers.cloudflare.com/bots/concepts/bot/signed-agents/).
* **Verified Bot Categories** (`cf.verified_bot_category`): A string that allows you to segment your verified bot traffic by its [type and purpose](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/#categories).

## Workers variables

These variables are also available as part of the [request.cf](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties) object via Cloudflare Workers:

* `request.cf.botManagement.score`
* `request.cf.botManagement.verifiedBot`
* `request.cf.botManagement.staticResource`
* `request.cf.botManagement.ja3Hash`
* `request.cf.botManagement.ja4`
* `request.cf.botManagement.jsDetection.passed`
* `request.cf.botManagement.detectionIds`
* `request.cf.botManagement.signedAgent`
* `request.cf.verifiedBotCategory`

## Corporate Proxy

The Bot Management Corporate Proxy field contains identified cloud-based corporate proxies and secure web gateways that are Enterprise-only, and provide outbound security services to their clients.

You can access the Corporate Proxy field in [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/), [Rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/), or [Workers](https://developers.cloudflare.com/workers/) to provide different security rules for traffic from these sources. You can also exempt them from rules using Bot Management scores.

Example

```

not cf.bot_management.verified_bot

and not cf.bot_management.static_resource

and not  cf.bot_management.corporate_proxy

and cf.bot_management.score lt 30


```

## Log fields

Once you enable Bot Management, Cloudflare also surfaces bot information in its [HTTP requests log fields](https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/zone/http%5Frequests/):

* BotDetectionIDs
* BotScore
* BotScoreSrc
* BotTags

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/reference/bot-management-variables/","name":"Bot Management variables"}}]}
```

---

---
title: IP validation
description: Verify bot identity by matching request IP addresses against published bot IP lists.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# IP validation

The IP validation method aims to identify all of the IP addresses that a bot may use to send requests. IP validation is only used as a verification method for [verified bots](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/).

Cloudflare can achieve this in two ways:

* **Using IP list provided by the bot owner**: The bot owner can host a public list of IP ranges (for example, [Googlebot's list ↗](https://developers.google.com/static/search/apis/ipranges/googlebot.json)). Cloudflare fetches and uses this list directly for validation.
* **Using Domain-based reverse DNS**: The bot owner can provide a domain (or set of domains) that their bot requests originate from. Cloudflare collects the IP addresses observed in the requests with the bot's user agent, and performs reverse DNS lookups. If the reverse DNS of an IP resolves to one of the provided domains, Cloudflare considers it valid and stores it.

## Public IP List

To verify a bot using a public IP list, you need to provide:

* A fixed and limited set of IP addresses, which can be verified via publicly accessible plain-text, `JSON`, or `CSV`.
* IP addresses used solely by the bot owner.
* A user-agent match pattern.

## Reverse DNS

To verify a bot using reverse DNS, you need to provide:

* A list of domain suffixes to validate DNS records.
* IP addresses should have PTR records set correctly.
* A user-agent match pattern.

## Generic user-agents

User-agent patterns that match generic user-agents will be rejected by the Verified Bots API. When you add a user-agent pattern that is considered very common to the Verified Bot form, you may encounter an error message that will prompt you to correct the user-agent before you can submit again.

Generic user-agents include:

* `Dart`
* `Go-http-client`
* `GuzzleHttp`
* `Google Chrome`
* `Mozilla Firefox`
* `Safari`
* `Nessus`
* `Websocket++`
* `cloudflare-go`
* `fasthttp`
* `got`
* `nginx-ssl early hints`
* `node`
* `node-fetch`
* `okhttp`
* `python-requests`
* `uTorrent`

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/reference/bot-verification/","name":"Bot verification methods"}},{"@type":"ListItem","position":5,"item":{"@id":"/bots/reference/bot-verification/ip-validation/","name":"IP validation"}}]}
```

---

---
title: Web Bot Auth
description: Verify bot identity using cryptographic HTTP message signatures.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Web Bot Auth

Web Bot Auth is an authentication method that leverages cryptographic signatures in HTTP messages to verify that a request comes from an automated bot. Web Bot Auth is used as a verification method for [verified bots](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/) and [signed agents](https://developers.cloudflare.com/bots/concepts/bot/signed-agents/).

It relies on two active IETF drafts: a [directory draft ↗](https://datatracker.ietf.org/doc/html/draft-meunier-http-message-signatures-directory) allowing the crawler to share their public keys, and a [protocol draft ↗](https://datatracker.ietf.org/doc/html/draft-meunier-web-bot-auth-architecture) defining how these keys should be used to attach crawler's identity to HTTP requests.

This documentation goes over specific integration within Cloudflare.

## 1\. Generate a valid signing key

You need to generate a signing key which will be used to authenticate your bot's requests.

1. Generate a unique [Ed25519 ↗](https://ed25519.cr.yp.to/) private key to sign your requests. This example uses the [OpenSSL ↗](https://openssl-library.org/) `genpkey` command:  
Note  
Cloudflare supports Ed25519 key algorithm.  
Terminal window  
```  
openssl genpkey -algorithm ed25519 -out private-key.pem  
```
2. Extract your public key.  
Terminal window  
```  
openssl pkey -in private-key.pem -pubout -out public-key.pem  
```
3. Convert the public key to JSON Web Key (JWK) using a tool of your choice. This example uses [jwker ↗](https://github.com/jphastings/jwker) command line application.  
Terminal window  
```  
go install github.com/jphastings/jwker/cmd/jwker@latest  
jwker public-key.pem public-key.jwk  
```

By following these steps, you have generated a private key and a public key, then converted the public key to a JWK.

Note

You can also [generate a JavaScript key using WebCrypto API ↗](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey), which will produce a key in the correct JWK format.

Many existing [JWK libraries ↗](https://jwt.io/libraries) support WebCrypto API for generating JavaScript key.

## 2\. Host a key directory

You need to host a key directory which creates a way for your bot to authenticate its requests to Cloudflare. This directory should follow the definition from the active IETF draft [draft-meunier-http-message-signatures-directory-01 ↗](https://datatracker.ietf.org/doc/html/draft-meunier-http-message-signatures-directory-01).

1. Host a key directory at `/.well-known/http-message-signatures-directory` (note that this is a requirement). This key directory should serve a JSON Web Key Set (JWKS) including the public key derived from your signing key.
2. Serve the web page over HTTPS (not HTTP).
3. [Calculate the base64 URL-encoded JWK thumbprint ↗](https://www.rfc-editor.org/rfc/rfc8037.html#appendix-A.3) associated with your Ed25519 public key.
4. Sign your HTTP response using the HTTP message signature specification by attaching one signature per key in your key directory. This ensures no one else can mirror your directory and attempt to register on your behalf. Your response must include the following headers:  
   * `Content-Type`: This header must have the value `application/http-message-signatures-directory+json`.  
   * `Signature`: Construct a [Signature header ↗](https://www.rfc-editor.org/rfc/rfc9421#name-the-signature-http-field) over your chosen components.  
   * `Signature-Input`: Construct a [Signature-Input header ↗](https://www.rfc-editor.org/rfc/rfc9421#name-the-signature-input-http-fi) over your chosen components. The header must meet the following requirements.  
   | Required component / parameter | Requirement                                                                                                                                                                                       |  
   | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |  
   | tag                            | This should be equal to http-message-signatures-directory.                                                                                                                                        |  
   | keyid                          | JWK thumbprint of the corresponding key in your directory.                                                                                                                                        |  
   | created                        | This should be equal to a Unix timestamp associated with when the message was sent by your application.                                                                                           |  
   | expires                        | This should be equal to a Unix timestamp associated with when Cloudflare should no longer attempt to verify the message.                                                                          |  
   | @authority                     | This should be equal to the value of the Host header sent by the request. You should set the [req component parameter ↗](https://datatracker.ietf.org/doc/html/rfc9421#content-request-response). |  
The following example shows the annotated request and response with required headers against `https://example.com`. The value of `Signature` here is purely for illustrative purposes, and not the actual generated signature.  
```  
GET /.well-known/http-message-signatures-directory HTTP/1.1  
Host: example.com  
Accept: application/http-message-signatures-directory+json  
HTTP/1.1 200 OK  
Content-Type: application/http-message-signatures-directory+json  
Signature: sig1=:TD5arhV1ved6xtx63cUIFCMONT248cpDeVUAljLgkdozbjMNpJGr/WAx4PzHj+WeG0xMHQF1BOdFLDsfjdjvBA==:  
Signature-Input: sig1=("@authority";req);alg="ed25519";keyid="poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U";nonce="ZO3/XMEZjrvSnLtAP9M7jK0WGQf3J+pbmQRUpKDhF9/jsNCWqUh2sq+TH4WTX3/GpNoSZUa8eNWMKqxWp2/c2g==";tag="http-message-signatures-directory";created=1750105829;expires=1750105839  
Cache-Control: max-age=86400  
{  
  "keys": [{  
    "kty": "OKP",  
    "crv": "Ed25519",  
    "x": "JrQLj5P_89iXES9-vFgrIy29clF9CC_oPPsw3c5D0bs", // Base64 URL-encoded public key, with no padding  
  }]  
}  
```

Note

This URL serves a standard JSON Web Key Set. Besides `x`, `crv`, and `kty`, you can include other standard JSON Web Key parameters, and you may publish non-Ed25519 keys as well. Multiple Ed25519 keys are supported. Only those for which you provide a signature in the above format are going to be used.

Cloudflare will ignore all other key types and key parameters except those containing `kty`, `crv`, and `x` formatted above. Do not include information that would leak your private key, such as the `d` parameter.

You can use the Cloudflare-developed [http-signature-directory CLI tool ↗](https://crates.io/crates/http-signature-directory) to assist you in validating your directory.

## 3\. Register your bot and key directory

You need to register your bot and its key directory to add your bot to the list of verified bots.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Manage Account** \> **Configurations**.
3. Go to the **Bot Submission Form** tab.
4. For **Verification Method**: select **Request Signature**.
5. For **Validation Instructions**: enter the URL of your key directory. You can additionally supply User Agents values (and their match patterns) that will be sent by your bot.
6. Select **Submit**.

Cloudflare accepts all valid Ed25519 keys found in your key directory. In the event a key already exists in Cloudflare's registered database, Cloudflare will work with you to supply a new key, or rotate your existing key.

After successful verification, you will be able to send verified requests.

## 4\. (After verification) Sign your requests

After your bot has been successfully verified, your bot is ready to sign its requests. The signature protocol is defined in [draft-meunier-web-bot-auth-architecture-02 ↗](https://datatracker.ietf.org/doc/html/draft-meunier-web-bot-auth-architecture-02)

### 4.1\. Choose a set of components to sign

Choose a set of components to sign.

A component is either an HTTP header, or any [derived components ↗](https://www.rfc-editor.org/rfc/rfc9421#name-derived-components) in the HTTP Message Signatures specification. Cloudflare recommends the following:

* Choose at least the `@authority` derived component, which represents the domain you are sending requests to. For example, a request to `https://example.com` will be interpreted to have an `@authority` of `example.com`.
* Use components that only contain ASCII values. HTTP Message Signature specification disallows non-ASCII characters, which will result in failure to validate your bot's requests.

Use components with only ASCII values

Cloudflare currently does not support `bs` or `sf` parameter designed to serialize non-ASCII values into ASCII equivalents.

`Content-Digest` header

If you wish to sign your [message content ↗](https://www.rfc-editor.org/rfc/rfc9421#name-message-content) using a `Content-Digest` header, note that you should only do so if there is zero risk of a message being altered on the way to Cloudflare.

For example, if the message is unencrypted and proxied to Cloudflare, you should not use `Content-Digest`.

### 4.2\. Calculate the JWK thumbprint

[Calculate the base64 URL-encoded JWK thumbprint ↗](https://www.rfc-editor.org/rfc/rfc8037.html#appendix-A.3) from the public key you registered with Cloudflare.

### 4.3\. Construct the required headers

Construct the three required headers for Web Bot Auth.

#### `Signature-Input` header

Construct a [Signature-Input header ↗](https://www.rfc-editor.org/rfc/rfc9421#name-the-signature-input-http-fi) over your chosen components. The header must meet the following requirements.

| Required component parameter | Requirement                                                                                                                                                                                                                                           |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| tag                          | This should be equal to web-bot-auth.                                                                                                                                                                                                                 |
| keyid                        | This should be equal to the thumbprint computed in step 2.                                                                                                                                                                                            |
| created                      | This should be equal to a Unix timestamp associated with when the message was sent by your application.                                                                                                                                               |
| expires                      | This should be equal to a Unix timestamp associated with when Cloudflare should no longer attempt to verify the message. A short expires reduces the likelihood of replay attacks, and Cloudflare recommends choosing suitable short-lived intervals. |

`nonce`

The `nonce` parameter allows you to supply a `nonce` to prevent attackers from replaying past messages against a server.

While Cloudflare recommends including it, there is currently no `nonce` validation, nor does Cloudflare guard against replay attacks using a database of seen `nonces`.

Instead, Cloudflare recommends short `expires` as a protection against replay attacks. A minute is often sufficient.

#### `Signature` header

Construct a [Signature header ↗](https://www.rfc-editor.org/rfc/rfc9421#name-the-signature-http-field) over your chosen components.

#### `Signature-Agent` header

Construct a [Signature-Agent header ↗](https://www.ietf.org/archive/id/draft-meunier-http-message-signatures-directory-01.html#name-header-field-definition) that points to your key directory. Note that Cloudflare will fail to verify a message if:

* The message includes a `Signature-Agent` header that is not an `https://`.
* The message includes a valid URI but does not enclose it in double quotes. This is due to Signature-Agent being a structured field.
* The message has a valid `Signature-Agent` header, but does not include it in the component list in `Signature-Input`.

### 4.4\. Add the headers to your bot's requests

Attach these three headers to your bot's requests.

An example request may look like this:

```

Signature-Agent: "https://signature-agent.test"

Signature-Input: sig2=("@authority" "signature-agent")

 ;created=1735689600

 ;keyid="poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U"

 ;alg="ed25519"

 ;expires=1735693200

 ;nonce="e8N7S2MFd/qrd6T2R3tdfAuuANngKI7LFtKYI/vowzk4lAZYadIX6wW25MwG7DCT9RUKAJ0qVkU0mEeLElW1qg=="

 ;tag="web-bot-auth"

Signature: sig2=:jdq0SqOwHdyHr9+r5jw3iYZH6aNGKijYp/EstF4RQTQdi5N5YYKrD+mCT1HA1nZDsi6nJKuHxUi/5Syp3rLWBA==:


```

Note

You can test how Cloudflare interprets your signed requests against [https://crawltest.com/cdn-cgi/web-bot-auth ↗](https://crawltest.com/cdn-cgi/web-bot-auth). This endpoint returns an HTTP `401` if your message is formatted correctly but your key is unknown, an HTTP `200` if the key is known and your message is verified, and an HTTP `400` otherwise. You may also see an HTTP `401` if your key is known but the message failed to verify.

---

## Limitations

Cloudflare's implementation of Web Bot Auth does not support every component and parameter defined in IETF RFC 9421\. If you include any of the following in your request's Signature-Input header, verification will fail.

* `@query-params`: Cloudflare recommends signing the whole query using the `@query` component instead of signing an individual parameter.
* `@status`: This is not possible to include in the request path.

The following component parameters defined in IETF RFC 9421 are not supported, and Cloudflare will fail to verify a message if they are included:

* `sf` (for HTTP header fields)
* `bs` (for HTTP header fields)
* `key` (for HTTP header fields)
* `req` (for HTTP header fields or derived components)
* `name` (for `@query-param` support - this requires `@query-param` support)

---

## Troubleshooting

### Failed message validation

If your message is failing validation, the cause(s) may include:

* Ensure you have a [Signature-Agent header](https://developers.cloudflare.com/bots/reference/bot-verification/web-bot-auth/#signature-agent-header), and that its value is in double-quotes.
* Ensure you include `signature-agent` in the component list in your [Signature-Input header](https://developers.cloudflare.com/bots/reference/bot-verification/web-bot-auth/#signature-agent-header).
* Ensure your `expires` timestamp is not too short, such that, by the time it arrives at Cloudflare servers, it has already expired. A minute is often sufficient.
* Ensure you are not signing components containing non-ASCII values, or on the unsupported list.

### Use HTTP message signatures / Web Bot Auth on a zone without Cloudflare's verification

If you wish to use HTTP Message Signatures (Web Bot Auth) for your own origin processing and do not want Cloudflare's verification to intervene or populate the `cf.bot_management.verified_bot` field, you can request that the Cloudflare verification feature be disabled for your zone.

To disable Web Bot Auth verification, contact [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/).

Disabling this feature means that Cloudflare will not validate incoming signatures. Verified bots will then fall back to other methods (such as reverse DNS validation) to determine if traffic is legitimate.

## Additional resources

You may wish to refer to the following resources.

* Cloudflare blog: [Message Signatures are now part of our Verified Bots Program ↗](https://blog.cloudflare.com/verified-bots-with-cryptography).
* Cloudflare blog: [Forget IPs: using cryptography to verify bot and agent traffic ↗](https://blog.cloudflare.com/web-bot-auth/).
* Cloudflare's [web-bot-auth library in Rust ↗](https://crates.io/crates/web-bot-auth).
* Cloudflare's [web-bot-auth npm package in Typescript ↗](https://www.npmjs.com/package/web-bot-auth).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/reference/bot-verification/","name":"Bot verification methods"}},{"@type":"ListItem","position":5,"item":{"@id":"/bots/reference/bot-verification/web-bot-auth/","name":"Web Bot Auth"}}]}
```

---

---
title: Machine Learning models
description: Manage auto-updates for Bot Management machine learning models.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Machine Learning models

## Enable auto-updates to the Machine Learning models

Cloudflare encourages Enterprise customers to enable auto-updates to its Machine Learning models to get the newest bot detection models as they are released.

To enable auto-updates:

* [  New dashboard ](#tab-panel-6706)
* [ Old dashboard ](#tab-panel-6707)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **Bot traffic**.
3. Go to **Bot Management**.
4. Under **Configurations**, select the edit icon for **Auto-updates to the Machine Learning Model** and turn it on.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Bots**.
3. Select **Configure Bot Management**.
4. Enable **Auto-updates to the Machine Learning Model**.

### What will change

If you are on an older Machine Learning model, you will see a score change to requests scored by the **Machine Learning** source instantly. If you are already on the latest model, you will see changes only after a new Machine Learning model becomes the global default.

Customers will be notified via email and dashboard prior to a new Machine Learning model becoming the global default.

### Risks of not updating

By not updating to the latest version, you will be using a Machine Learning model no longer maintained or monitored by our engineering team. As Internet traffic changes and new trends evolve, scoring accuracy by older versions may degrade.

### Model versions and release notes

| Version | Release Notes                                                                                                                                                                                                                     | Launch Date |
| ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| v1      | First Machine Learning Model released.                                                                                                                                                                                            | Q1 2019     |
| v2      | Introduced dynamic inter-request features to leverage the Cloudflare network to detect new bots more accurately. Feedback other Bot Management detection mechanisms to the machine learning model to more accurately detect bots. | Q1 2020     |
| v3      | Fixed accuracy issues under some conditions in the previous version.                                                                                                                                                              | Q2 2020     |
| v4      | Improved scoring for iOS devices. Fixed scoring inaccuracy in Firefox builds.                                                                                                                                                     | Q1 2021     |
| v5      | Recalibrated model for the [removal of \_cfduid cookie ↗](https://blog.cloudflare.com/deprecating-cfduid-cookie/).  Introduced new signals to reduce false negatives.                                                             | Q2 2021     |
| v6      | Significantly improved scoring for native Android application traffic. Improved scoring on the newest versions of Chromium browsers.                                                                                              | Q1 2022     |
| v7      | Increased recognition of distributed botnets. Improved HTTP/3 scoring.                                                                                                                                                            | Q1 2024     |
| v8      | Improved detection of residential proxies. Increased weight on network level traffic characteristics.                                                                                                                             | Q2 2024     |
| v9      | Improved model consistency and model efficacy against randomization attack techniques                                                                                                                                             | Q2 2025     |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/reference/machine-learning-models/","name":"Machine Learning models"}}]}
```

---

---
title: Sample terms
description: Example Terms of Service language for restricting AI bots and data scraping.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Sample terms

Cloudflare recommends that customers consider updating their Terms of Service to address bots specifically related to Artificial Intelligence (AI) training and data scraping. The text below provides an informational example of the kind of language that could be added to a website's terms of use.

> **Artificial Intelligence Restriction**
> 
> You may not use automated bots to access, scan, scrape, data mine, copy, or use the materials or content on this website for developing, training, fine-tuning, or otherwise contributing to or improving a machine learning model or artificial intelligence (AI) system or the operation thereof, unless your bot's user agent is (I) explicitly permitted ("allowed") to do so in this website's `robots.txt` file and (II) solely used to identify bots used for AI purposes (i.e., this provision does not apply to user agents that are used for multiple purposes, such as search engine indexing and AI purposes).

Disclaimer

This language is provided for informational purposes only. It does not constitute legal advice, nor does it guarantee any specific outcome.

This is an illustrative example of language that can be included in a website's terms to put AI providers on notice that they are not authorized to use automated means to scrape content from your website for purposes of training or otherwise contributing to their AI models or systems, unless you have expressly permitted them to do so in your `robots.txt` file.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/reference/sample-terms/","name":"Sample terms"}}]}
```

---

---
title: Bot Management skips
description: Understand why Bot Management does not score certain requests.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Bot Management skips

There are instances in which Bot Management does not run and certain fields, such as the [JA3/JA4 field](https://developers.cloudflare.com/bots/additional-configurations/ja3-ja4-fingerprint/), are not populated because it has been determined that running Bot Management would not be necessary.

Refer to [bot scores](https://developers.cloudflare.com/bots/concepts/bot-score/#not-computed) for more information about why a request is not scored.

## Common reasons for Bot Management to not score a request

### Requests to internal endpoints

Requests such as `/cdn-cgi/` are handled individually and will never receive a Bot Management score. Email Obfuscation, Web Analytics, Trace Requests, Challenge Pages, and JavaScript Detections do not receive bot scores. Refer to the table below for some examples of internal endpoints.

| Route                                                           |
| --------------------------------------------------------------- |
| /cdn-cgi/rum                                                    |
| /cdn-cgi/script\_monitor/report                                 |
| /cdn-cgi/trace                                                  |
| /cdn-cgi/challenge-platform/…                                   |
| /cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js |

### Purge requests

All HTTP purge requests will not receive a bot score.

### Early hints cache requests

Early hints cache requests will not receive a bot score.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/troubleshooting/bot-management-skips/","name":"Bot Management skips"}}]}
```

---

---
title: Handle False Positives from Bot Fight Mode or Super Bot Fight Mode
description: Resolve false positives where legitimate traffic is blocked by bot protection.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Handle False Positives from Bot Fight Mode or Super Bot Fight Mode

[Bot Fight Mode (BFM)](https://developers.cloudflare.com/bots/get-started/bot-fight-mode/) and [Super Bot Fight Mode (SBFM)](https://developers.cloudflare.com/bots/get-started/bot-fight-mode/) are designed to stop active attacks quickly. Due to their aggressive nature, false positives can occur where legitimate human or automated traffic is incorrectly challenged or blocked.

When dealing with false positives, consider the following key differences and solutions:

* Bot Fight Mode has limited control. You cannot bypass or skip Bot Fight Mode using the _Skip_ action in WAF custom rules or using Page Rules. Bot Fight Mode will be disabled if there are any IP Access rules present. If you turned on BFM during an attack, and the attack has subsided, we recommend either disabling the feature using IP Access rules to bypass BFM, or looking at [Bot Management for Enterprise](https://developers.cloudflare.com/bots/plans/bm-subscription/), which gives you the ability to precisely customize your security threshold and create exception rules as needed.
* Super Bot Fight Mode can be bypassed with IP Access _Allow_ action rules. You can use the _Skip_ action in [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/skip/) to specify where Super Bot Fight Mode should not run.

In parts of your site where you want bot traffic, you can use the [_Skip_ action](https://developers.cloudflare.com/waf/custom-rules/skip/) in [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/) to specify where Super Bot Fight Mode should not run.

You can use the [Rules language](https://developers.cloudflare.com/ruleset-engine/rules-language/) and its [operators](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/) and [fields](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/) in custom rules to configure a scoped rule for approved automated traffic in Super Bot Fight Mode.

You cannot bypass or skip Bot Fight Mode using the _Skip_ action in WAF custom rules or using Page Rules. _Skip_, _Bypass_, and _Allow_ actions apply to rules or rulesets running on the [Ruleset Engine](https://developers.cloudflare.com/ruleset-engine/). While Super Bot Fight Mode rules are implemented in the Ruleset Engine, Bot Fight Mode checks are not. This is why you can skip Super Bot Fight Mode, but not Bot Fight Mode. If you need to skip Bot Fight Mode, consider using [Super Bot Fight Mode](https://developers.cloudflare.com/bots/get-started/super-bot-fight-mode/).

Bot Fight Mode can still trigger if you have IP Access rules, but it cannot trigger if an IP Access rule matches the request. For example, the IP Access rule matches the connecting IP.

If you encounter persistent false positives, you can [disable the feature in the Cloudflare dashboard](https://developers.cloudflare.com/bots/get-started/bot-fight-mode/#disable-bot-fight-mode).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/troubleshooting/false-positives/","name":"Handle False Positives from Bot Fight Mode or Super Bot Fight Mode"}}]}
```

---

---
title: Super Bot Fight Mode for WordPress
description: Fix WordPress loopback errors caused by Super Bot Fight Mode blocking diagnostics.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Super Bot Fight Mode for WordPress

When users attempt to run diagnostics in the Site Status page for WordPress installations, loopback issues arise when our bot detection services block them.

WordPress relies on making loopback requests to monitor and occasionally administer its websites. Customers can opt-in to optimize Super Bot Fight Mode for WordPress. If this feature is enabled, automated loopback requests made by your WordPress site will be authorized even when Super Bot Fight Mode blocks other bots.

Note

Loopback requests may also be blocked by [I’m Under Attack mode](https://developers.cloudflare.com/fundamentals/reference/under-attack-mode/) or certain [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/).

## Enable Optimize for WordPress

* [  New dashboard ](#tab-panel-6708)
* [ Old dashboard ](#tab-panel-6709)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **Bot traffic**.
3. Go to **Super Bot Fight Mode**.
4. Under **Configurations**, select the edit icon for **Optimize for WordPress** and turn it on.

1. Log in to the [Cloudflare dashboard ↗](http://dash.cloudflare.com), and select your account and domain.
2. Go to **Security** \> **Bots**.
3. Select **Configure Bot Management**.
4. Enable **Optimize for WordPress**.

## Availability

This feature is available for all Super Bot Fight Mode customers.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/troubleshooting/wordpress-loopback-issue/","name":"Super Bot Fight Mode for WordPress"}}]}
```

---

---
title: Delay action
description: Use a Worker to add configurable delays to requests with low bot scores.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Delay action

Customers with a Bot Management and a [Workers](https://developers.cloudflare.com/workers/) subscription can use the template below to introduce a delay to requests that are likely from bots.

The template sets a minimum and maximum delay, and delays requests where the bot score is less than 30 and the URI path starts with `/exampleURI`.

* [  JavaScript ](#tab-panel-6710)
* [  TypeScript ](#tab-panel-6711)

JavaScript

```

// Configurable Variables

const PATH_START = "/exampleURI";

const DELAY_FROM = 5; // in seconds

const DELAY_TO = 10; // in seconds


export default {

  async fetch(request, env, ctx) {

    const url = new URL(request.url);

    const botScore = request.cf.botManagement.score;


    if (url.pathname.startsWith(PATH_START) && botScore < 30) {

      // Random delay between DELAY_FROM and DELAY_TO seconds

      const delay =

        Math.floor(Math.random() * (DELAY_TO - DELAY_FROM + 1)) + DELAY_FROM;

      await new Promise((resolve) => setTimeout(resolve, delay * 1000));


      // Fetch the original request

      return fetch(request);

    }


    // Fetch the original request without delay

    return fetch(request);

  },

};


```

TypeScript

```

// Configurable Variables

const PATH_START = '/exampleURI';

const DELAY_FROM = 5; // in seconds

const DELAY_TO = 10; // in seconds


export default {

  async fetch(request, env, ctx): Promise<Response> {

    const url = new URL(request.url);

    const botScore = request.cf.botManagement.score


    if (url.pathname.startsWith(PATH_START) && botScore < 30) {

      // Random delay between DELAY_FROM and DELAY_TO seconds

      const delay = Math.floor(Math.random() * (DELAY_TO - DELAY_FROM + 1)) + DELAY_FROM;

      await new Promise(resolve => setTimeout(resolve, delay * 1000));


      // Fetch the original request

      return fetch(request);

    }


    // Fetch the original request without delay

    return fetch(request);

  },

} satisfies ExportedHandler<Env>;


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/bots/","name":"Bots"}},{"@type":"ListItem","position":3,"item":{"@id":"/bots/workers-templates/","name":"Workers templates"}},{"@type":"ListItem","position":4,"item":{"@id":"/bots/workers-templates/delay-action/","name":"Delay action"}}]}
```

---

---
title: Client-side security
description: Cloudflare's client-side security is a comprehensive client-side security and privacy solution that allows you to ensure the safety of your website visitors' browsing environment.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Client-side security

Ensures the safety and privacy of your website visitors' browsing environment.

 Available on all plans 

Websites load third-party scripts for analytics, ads, chat widgets, and payment forms. If an attacker compromises one of these scripts, they can steal visitor data directly from the browser, an attack known as a [client-side supply chain attack ↗](https://www.cloudflare.com/learning/security/what-is-a-supply-chain-attack/). Client-side security (formerly Page Shield) gives you visibility into these resources and alerts you when something changes or looks malicious.

Client-side security monitors scripts, connections, and cookies loaded by your website visitors. You can set up alert notifications and create content security rules to control which resources are allowed on your pages.

Learn how to [get started](https://developers.cloudflare.com/client-side-security/get-started/).

---

## Features

###  Resource monitoring 

Displays information about client-side resources loaded in your domain's pages.

[ Monitor client-side resources ](https://developers.cloudflare.com/client-side-security/detection/monitor-connections-scripts/) 

###  Page attribution 

Find in which page a resource first appeared, and view a list of the latest occurrences of the resource in your pages.

[ Find resource occurrences ](https://developers.cloudflare.com/client-side-security/detection/monitor-connections-scripts/#view-details) 

###  Malicious script detection 

Detects malicious scripts in your pages using threat intelligence and machine learning.

[ Review malicious scripts ](https://developers.cloudflare.com/client-side-security/detection/review-malicious-scripts/) 

###  Code change detection 

Detects any changes in the scripts loaded in your pages.

[ Review changed scripts ](https://developers.cloudflare.com/client-side-security/detection/review-changed-scripts/) 

###  Alerts 

Receive notifications about newly detected scripts, scripts loaded from unknown domains, new scripts considered malicious, or code changes in your existing scripts.

[ Use Alerts ](https://developers.cloudflare.com/client-side-security/alerts/) 

###  Content security rules 

Content security rules define allowed resources on your websites. Use content security rules to enforce an allowlist of resources, effectively blocking resources not included in your rules.

[ Use Content security rules ](https://developers.cloudflare.com/client-side-security/rules/) 

## Availability

| Free                                                 | Pro | Business | Enterprise | Advanced |     |
| ---------------------------------------------------- | --- | -------- | ---------- | -------- | --- |
| Availability                                         | Yes | Yes      | Yes        | Yes      | Yes |
| Script monitoring                                    | Yes | Yes      | Yes        | Yes      | Yes |
| Connection monitoring                                | No  | No       | Yes        | Yes      | Yes |
| Cookie monitoring                                    | No  | No       | Yes        | Yes      | Yes |
| Page attribution                                     | No  | No       | Yes        | Yes      | Yes |
| New Resources Alerts and New Domain Alerts           | No  | No       | Yes        | Yes      | Yes |
| Malicious script detection and alerting              | No  | No       | No         | No       | Yes |
| Code change detection and alerting                   | No  | No       | No         | No       | Yes |
| Malicious connection detection and alerting          | No  | No       | No         | No       | Yes |
| Cookie monitoring advanced fields                    | No  | No       | No         | No       | Yes |
| Number of content security rules (positive blocking) | 0   | 0        | 0          | 0        | 5   |
| Number of Logpush jobs                               | 0   | 0        | 0          | 0        | 4   |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}}]}
```

---

---
title: Get started with client-side security
description: Learn how to get started with Cloudflare's client-side security.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started with client-side security

## 1\. Activate client-side resource monitoring

To enable client-side resource monitoring:

* [  New dashboard ](#tab-panel-6841)
* [ Old dashboard ](#tab-panel-6842)

1. In the Cloudflare dashboard, go to the Security **Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. (Optional) Filter by **Client-side abuse**.
3. Turn on **Continuous script monitoring**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Client-side security**.
3. Go to the **Settings** tab.
4. Next to **Continuous monitoring and alerting**, select **Enable**.

If you do not have access to client-side security settings in the Cloudflare dashboard, check if your user has one of the [necessary roles](https://developers.cloudflare.com/client-side-security/reference/roles-and-permissions/).

## 2\. Review detected resources

When you enable client-side resource monitoring, it may take a while to get the list of detected scripts in your domain.

To review the scripts detected by Cloudflare:

1. Go to the client-side resources page:  
   * [  New dashboard ](#tab-panel-6839)  
   * [ Old dashboard ](#tab-panel-6840)  
   1. In the Cloudflare dashboard, go to the **Web assets** page.  
   [ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)  
   2. Select the **Client-side resources** tab.  
   1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.  
   2. Go to **Security** \> **Client-side security**.
2. Review the list of detected scripts, checking for any unknown or unexpected scripts. [Depending on your plan and subscriptions](https://developers.cloudflare.com/client-side-security/#availability), Cloudflare will also:  
   * Inform you if a script is [considered malicious](https://developers.cloudflare.com/client-side-security/how-it-works/malicious-script-detection/).  
   * [Show the details](https://developers.cloudflare.com/client-side-security/detection/monitor-connections-scripts/#view-details) about each detected script.

Depending on your Cloudflare plan, you may be able to also review the connections made by scripts in your domain's pages and check them for malicious activity.

## 3\. (Optional) Configure alerts

Once you have activated client-side security's resource monitoring, you can set up one or more alerts informing you of relevant client-side changes on your zones. The [available alert types](https://developers.cloudflare.com/client-side-security/alerts/alert-types/) depend on your Cloudflare plan and subscriptions.

To configure an alert:

1. In the Cloudflare dashboard, go to the **Notifications** page.  
[ Go to **Notifications** ](https://dash.cloudflare.com/?to=/:account/notifications)
2. Choose **Add** and then select **Client-side security (formerly Page Shield)** in the **Product** dropdown.
3. Select an [alert type](https://developers.cloudflare.com/client-side-security/alerts/alert-types/).
4. Enter the notification name and description.
5. (Optional) If you are a customer with Client-Side Security Advanced, you can [define the zones for which you want to filter alerts](https://developers.cloudflare.com/client-side-security/alerts/#scoped-alerts) in **Rules of these zones**. This option requires that you define [content security rules](https://developers.cloudflare.com/client-side-security/rules/) in the selected zones.
6. Select one or more notification destinations (notification email, webhooks, and connected notification services).
7. Select **Create**.

To learn how you can handle an alert, refer to [Handle a client-side resource alert](https://developers.cloudflare.com/client-side-security/best-practices/handle-an-alert/).

## 4\. (Optional) Define content security rules

Note

Only available to customers with Client-Side Security Advanced.

[Content security rules](https://developers.cloudflare.com/client-side-security/rules/) (previously called policies) define allowed resources on your websites. Create content security rules to implement a positive security model[1](#user-content-fn-1).

### 4.1\. Create a content security rule with the Log action

When you create a content security rule with the [_Log_ action](https://developers.cloudflare.com/client-side-security/rules/#rule-actions), Cloudflare logs any resources not covered by the rule, without blocking any resources. Use this action to validate a new rule before deploying it.

Note

Only available to customers with Client-Side Security Advanced.

* [  New dashboard ](#tab-panel-6845)
* [ Old dashboard ](#tab-panel-6846)

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. Select **Create** \> **Content security rules**.
3. Enter a descriptive name for the rule in **Description**.
4. Under **If incoming requests match**, define the scope of the content security rule (or policy). You can use the Expression Builder (specifying one or more values for **Field**, **Operator**, and **Value**) or manually enter an expression using the Expression Editor. For more information, refer to [Edit expressions in the dashboard](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/edit-expressions/).
5. Under **Allow these directives**, select the desired [CSP directives](https://developers.cloudflare.com/client-side-security/rules/csp-directives/) for the content security rule by enabling one or more checkboxes.  
   * To manually enter an allowed source, select **Add source**.  
   * To refresh the displayed sources based on detected resources, select **Refresh suggestions**.  
   Note  
   Cloudflare provides suggestions for **Default**, **Scripts**, and **Connections** directives. For the **Default** directive, suggestions are based on monitored scripts and connections resources.
6. Under **Then take action**, select _Log_.
7. To save and deploy your rule, select **Deploy**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com) and select your account and domain.
2. Go to **Security** \> **Client-side security** \> **Rules**.
3. Select **Create rule**.
4. Enter a descriptive name for the rule in **Description**.
5. Under **If incoming requests match**, define the rule scope. You can use the Expression Builder (specifying one or more values for **Field**, **Operator**, and **Value**) or manually enter an expression using the Expression Editor. For more information, refer to [Edit expressions in the dashboard](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/edit-expressions/).
6. Under **Allow these directives**, select the desired [CSP directives](https://developers.cloudflare.com/client-side-security/rules/csp-directives/) for the rule by enabling one or more checkboxes.  
   * To manually enter an allowed source, select **Add source**.  
   * To refresh the displayed sources based on detected resources, select **Refresh suggestions**.  
   Note  
   Cloudflare provides suggestions for **Default**, **Scripts**, and **Connections** directives. For the **Default** directive, suggestions are based on monitored scripts and connections resources.
7. Under **Then take action**, select _Log_.
8. To save and deploy your rule, select **Deploy**.

### 4.2\. Review rule violations

Resources not covered by the content security rule you created will be reported as [rule violations](https://developers.cloudflare.com/client-side-security/rules/violations/). After some time, review the list of rule violations to make sure the rule is correct.

To view rule violation information:

* [  New dashboard ](#tab-panel-6843)
* [ Old dashboard ](#tab-panel-6844)

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. (Optional) Filter by **Content security rules**.

* In the Cloudflare dashboard, go to **Security** \> **Client-side security** \> **Rules**.

The displayed information includes the following:

* A sparkline next to the rule name, showing violations in the past seven days.
* For content security rules with associated violations, an expandable details section for each rule, with the top resources present in violation events and a sparkline per top resource.

Update the rule if needed.

### 4.3\. Change rule action to Allow

Once you have verified that your content security rule is correct, change the rule action from _Log_ to _Allow_.

When you use the [_Allow_ action](https://developers.cloudflare.com/client-side-security/rules/#rule-actions), Cloudflare starts blocking any resources not explicitly allowed by the rule.

## Footnotes

1. A positive security model is one that defines what is allowed and rejects everything else. In contrast, a negative security model defines what will be rejected and accepts the rest. [↩](#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":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/get-started/","name":"Get started with client-side security"}}]}
```

---

---
title: How client-side security works
description: Cloudflare's client-side security tracks resources (such as scripts) loaded by your website visitors and provides alerts when it detects new, changed, or malicious resources.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# How client-side security works

Cloudflare's client-side security helps manage client-side resources (which include scripts and their connections) loaded by your website visitors, and provides visibility on the [cookies ↗](https://www.cloudflare.com/learning/privacy/what-are-cookies/) recently detected in HTTP traffic. Client-side security can trigger alert notifications when resources change or are considered malicious.

Client-side security works by adding [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) HTTP headers to your site's responses. CSP is a browser-native mechanism that controls which resources a page is allowed to load and where to send reports when a resource violates the policy. Cloudflare uses two types of CSP headers for different purposes:

* For resource monitoring (scripts and connections)
* To enforce content security rules or log violations of these rules

## Comparison of CSP headers

The following table compares the CSP HTTP headers used for monitoring resources and applying content security rules:

| Resource monitoring HTTP header               | Content security rules HTTP headers                                                  |
| --------------------------------------------- | ------------------------------------------------------------------------------------ |
| content-security-policy-report-only           | content-security-policy-report-only (log rules)content-security-policy (allow rules) |
| Automatic — on when monitoring is enabled     | Manual — created via rules you define                                                |
| Added to a sample of HTML responses           | Added to 100% of matching responses (not sampled)                                    |
| Reports all detected scripts and connections  | CSP directives come from your allowlist                                              |
| Browser sends violation reports to Cloudflare | Log rules report violations onlyAllow rules block disallowed resources               |

## Header used for resource monitoring

When you turn on resource monitoring, Cloudflare automatically adds a `content-security-policy-report-only` HTTP header to a sample of HTML responses. This report-only header does not block anything. It uses CSP directives that cause browsers to generate violation reports for detected scripts and connections. For details on the header format, refer to [CSP HTTP header format](https://developers.cloudflare.com/client-side-security/reference/csp-header/).

Based on these reports, Cloudflare builds a list of all scripts running on your application and the connections they make to third-party endpoints. Cloudflare also monitors ingress and egress HTTP traffic for cookies, whether set by origin servers or by the visitor's browser.

You cannot turn off the monitoring header while resource monitoring is enabled. Because the header is added to a sample of responses, there may be a [small delay](https://developers.cloudflare.com/client-side-security/troubleshooting/#cloudflare-does-not-show-any-client-side-resources-after-activation) between deploying a script or cookie and having its data displayed in the resource monitoring dashboards.

The client-side resource monitoring dashboard shows the list of [active](https://developers.cloudflare.com/client-side-security/reference/script-statuses/#available-statuses) scripts, connections, and cookies. The **All Reported Scripts** and **All Reported Connections** dashboards show the full list of detected scripts and connections in your domain, respectively, including infrequent and inactive ones.

## Headers related to content security rules

When you create [content security rules](https://developers.cloudflare.com/client-side-security/rules/), Cloudflare generates CSP directives based on your allow and log rules:

* **Log rules** add directives to the `content-security-policy-report-only` HTTP header, reporting violations without blocking resources.
* **Allow rules** add directives to the `content-security-policy` HTTP header, actively blocking resources not present in your allowlist.

Unlike headers used for resource monitoring, these HTTP headers apply only to responses matching the expression you define in each rule and are not sampled. You have full control over these headers through your [content security rules](https://developers.cloudflare.com/client-side-security/rules/) configuration.

Customers with Client-Side Security Advanced have access to additional classification mechanisms based on threat feeds to determine if a script, or a connection made by a script, is malicious. For more information, refer to [Malicious script and connection detection](https://developers.cloudflare.com/client-side-security/how-it-works/malicious-script-detection/).

---

## Learn more

For more background on client-side security and resource monitoring, refer to our [blog post ↗](https://blog.cloudflare.com/page-shield-generally-available/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/how-it-works/","name":"How client-side security works"}}]}
```

---

---
title: Malicious script and connection detection
description: Cloudflare analyzes the JavaScript code of the scripts loaded by your website visitors, using threat intelligence and machine learning (including LLMs) to detect malicious behavior.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Malicious script and connection detection

Note

Domain-based threat intelligence is available to all customers. Malicious script detection and malicious URL checks require Client-Side Security Advanced.

Cloudflare uses three complementary mechanisms to determine if a script, or a connection made by a script, is malicious. Each mechanism checks at a different level — the script's code, the URL it is hosted at, or the domain it is served from:

* **Malicious script detection** — Analyzes the actual JavaScript code for malicious behavior.
* **Malicious URL checks** — Looks up script URLs against threat intelligence feeds.
* **Malicious domain checks** — Looks up script domains against threat intelligence feeds.

Any updates to the threat feeds will trigger new checks for previously detected scripts or connections so that the client-side resource monitoring dashboards always reflect the latest categorization.

## Malicious script detection

Cloudflare analyzes the JavaScript code of the scripts loaded by your website visitors. This analysis uses machine learning, including an LLM powered by Workers AI, to reduce the false positive rate and focus on highlighting true positives such as [Magecart-type attacks ↗](https://sansec.io/what-is-magecart), where injected code skims payment card data from checkout forms.

Note

Cloudflare uses open-source models for this analysis. Customer data is not used to train these models.

The analysis assigns a JS integrity score between 1 and 99 to each script version. Lower scores indicate higher risk: a score of 1 means definitely malicious, and 99 means definitely not malicious.

Cloudflare classifies a script as malicious when its score falls below the threshold, which is currently set to 10\. Scripts that score below this threshold appear as malicious in the monitoring dashboards.

In addition to the integrity score, Cloudflare will also provide individual scores for different malicious code detections (scores from 1 to 99):

* **Magecart**
* **Crypto mining**
* **Malware**

You can [configure Malicious Script Alerts](https://developers.cloudflare.com/client-side-security/alerts/configure/) to receive an alert notification as soon as Cloudflare detects JavaScript code classified as malicious in your domain.

Note

Currently, the script classifier only runs on scripts up to 300 KB. It is recommended that you take into account other signals in your monitoring strategy, such as signals based on threat intelligence feeds (malicious URL/domain checks).

## Malicious URL checks

Cloudflare will search for the URLs of your JavaScript dependencies in threat intelligence feeds to determine if any of those scripts should be categorized as malicious.

The client-side resource monitoring dashboards display the scripts that were considered malicious at the top of the scripts list.

You can [configure Malicious URL Alerts](https://developers.cloudflare.com/client-side-security/alerts/configure/) to receive an alert notification as soon as Cloudflare detects a script from a malicious URL in your domain.

Depending on your current configuration, Cloudflare can also search for malicious URLs in the URLs of outgoing connections made by scripts in your domain. To enable this check, you must [allow resource monitoring to use the full URLs of outgoing connections](https://developers.cloudflare.com/client-side-security/reference/settings/#connection-target-details) instead of only the hostname in the settings page.

## Malicious domain checks

Cloudflare will search for the domains of your client-side JavaScript dependencies in threat feeds to determine if any of those scripts is being served from a known malicious domain.

A domain previously reported as malicious can later be reported as non-malicious if, after further analysis, the domain is deemed safe.

Cloudflare will also check the target domains of connections made by scripts in your domain's pages, following the same approach described for scripts.

You can [configure Malicious Domain Alerts](https://developers.cloudflare.com/client-side-security/alerts/configure/) to receive an alert notification as soon as Cloudflare detects a malicious script loaded from a known malicious domain in your domain.

---

## Malicious script and connection categories

Scripts and connections considered malicious are categorized based on data from threat intelligence feeds. The current categories are the following:

* Security threats
* Command-and-Control (C2) & Botnet
* Crypto mining
* Spyware
* Phishing
* Malware
* Domain Generation Algorithm (DGA) domain
* Typosquatting & Impersonation

Each script or connection considered malicious can belong to several categories.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/how-it-works/","name":"How client-side security works"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/how-it-works/malicious-script-detection/","name":"Malicious script and connection detection"}}]}
```

---

---
title: Alerts
description: Cloudflare client-side resource alerts notify you when new scripts are detected on your domain or when Cloudflare detects resources that are likely malicious.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Alerts

Note

New resource alerts require a Business plan or higher. Code change and malicious resource alerts require Client-Side Security Advanced. For details, refer to [Alert types](https://developers.cloudflare.com/client-side-security/alerts/alert-types/).

Once you have activated client-side security's resource monitoring, you can set up one or more alerts informing you of relevant client-side changes on your zones. 

You can configure unscoped or scoped alerts:

* **Unscoped alert**: Covers all zones in your Cloudflare account. Unscoped alerts are triggered either daily, hourly, or immediately, depending on the [alert type](https://developers.cloudflare.com/client-side-security/alerts/alert-types/).
* **Scoped alert**: Covers one or more specific zones. Requires [content security rules](https://developers.cloudflare.com/client-side-security/rules/) configured in those zones. Scoped alerts are triggered immediately and only notify you about resources that are covered by your rules. [Rule violations](https://developers.cloudflare.com/client-side-security/rules/violations/) do not trigger these alerts. For more information, refer to [Scoped alerts](#scoped-alerts).

For alerts sent at regular intervals, you might experience a delay between adding a new script and receiving an alert.

For instructions on configuring alerts, refer to [Configure an alert](https://developers.cloudflare.com/client-side-security/alerts/configure/).

## Scoped alerts

Note

Only available to customers with Client-Side Security Advanced.

If you have configured [content security rules](https://developers.cloudflare.com/client-side-security/rules/) in a zone, you can filter alert notifications according to those rules. These alerts are called scoped alerts.

When you create a scoped alert using the **Policies of these zones** alert filter, you will only receive the most relevant notifications based on the rules you configured.

For each scoped alert, Cloudflare does the following:

1. Check which content security rules are enabled in a zone, either in allow or in log mode.
2. For every enabled rule, compare the URL of the new or changed resource against the allowed sources in the rule.
3. If the resource is allowed by the rule, check if the new or modified resource should trigger the current alert.
4. If the alert should trigger, send an alert notification to the configured destinations.

When you create a scoped alert you will not receive notifications for resources that are not allowed by a content security rule (either [in allow or in log mode](https://developers.cloudflare.com/client-side-security/rules/#rule-actions)). These are [rule violations](https://developers.cloudflare.com/client-side-security/rules/violations/) that you can review in the dashboard, through GraphQL, or via Logpush.

Note

Scoped alerts only fire if the zone has at least one enabled content security rule.

For unscoped alerts, you will receive notifications for all resources detected across your zones. Some of these resources may also violate your configured content security rules.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/alerts/","name":"Alerts"}}]}
```

---

---
title: Alert types
description: Available alert types for client-side resource detection, including new and malicious scripts.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Alert types

You can configure alerts for resources detected in your domain. Refer to [Alerts](https://developers.cloudflare.com/client-side-security/alerts/) for more information.

## New resource alerts

Note

Requires a Business plan or higher.

New resource alerts notify you about new resources detected on your domain, resources detected from new host domains, or issues with the URL length of newly detected resources.

Client-side security New Resources Alert

**Who is it for?**

[Client-side security](https://developers.cloudflare.com/client-side-security/) customers who want to receive a notification when new resources appear in their domain.

**Other options / filters**

None.

**Included with**

Business plans or higher.

**What should you do if you receive one?**

Investigate to confirm that it is an expected change.

**Additional information**

Triggered daily. If configured with a zone filter, the alert is triggered immediately.

Client-side security New Domain Alert

**Who is it for?**

[Client-side security](https://developers.cloudflare.com/client-side-security/) customers who want to receive a notification when resources from new host domains appear in their domain.

**Other options / filters**

None.

**Included with**

Business plans or higher.

**What should you do if you receive one?**

Investigate to confirm that it is an expected change.

**Additional information**

Triggered hourly. If configured with a zone filter, the alert is triggered immediately.

Client-side security New Resource Exceeds Max URL Length Alert

**Who is it for?**

[Client-side security](https://developers.cloudflare.com/client-side-security/) customers who want to receive a notification when a resource's URL exceeds the maximum allowed length.

**Other options / filters**

None.

**Included with**

Business plans or higher.

**What should you do if you receive one?**

Manually check the resource.

## Code change alert

Note

Only available to customers with Client-Side Security Advanced.

This alert notifies you about [code changes](https://developers.cloudflare.com/client-side-security/detection/review-changed-scripts/) in previously detected scripts.

Client-side security New Code Change Detection Alert

**Who is it for?**

[Client-side security](https://developers.cloudflare.com/client-side-security/) customers who want to receive a notification when JavaScript dependencies change in the pages of their domain.

**Other options / filters**

None.

**Included with**

Customers with Client-Side Security Advanced.

**What should you do if you receive one?**

Investigate to confirm that it is an expected change.

**Additional information**

Triggered daily. If configured with a zone filter, the alert is triggered immediately.

## Malicious resource alerts

Note

Only available to customers with Client-Side Security Advanced.

Malicious resource alerts notify you about [resources considered malicious](https://developers.cloudflare.com/client-side-security/how-it-works/malicious-script-detection/), based on their [domain](https://developers.cloudflare.com/client-side-security/how-it-works/malicious-script-detection/#malicious-domain-checks), [URL](https://developers.cloudflare.com/client-side-security/how-it-works/malicious-script-detection/#malicious-url-checks), or [script content](https://developers.cloudflare.com/client-side-security/how-it-works/malicious-script-detection/#malicious-script-detection).

Client-side security New Malicious Domain Alert

**Who is it for?**

[Client-side security](https://developers.cloudflare.com/client-side-security/) customers who want to receive a notification when resources from a known malicious domain appear in their domain. For more information, refer to [Malicious script and connection detection](https://developers.cloudflare.com/client-side-security/how-it-works/malicious-script-detection/).

**Other options / filters**

None.

**Included with**

Customers with Client-Side Security Advanced.

**What should you do if you receive one?**

Review the information in the client-side security dashboard about the detected malicious resources, then update the pages where those resources were detected.

For more information, refer to [Review scripts and connections considered malicious](https://developers.cloudflare.com/client-side-security/detection/review-malicious-scripts/).

Client-side security New Malicious URL Alert

**Who is it for?**

[Client-side security](https://developers.cloudflare.com/client-side-security/) customers who want to receive a notification when resources from a known malicious URL appear in their domain. For more information, refer to [Malicious script and connection detection](https://developers.cloudflare.com/client-side-security/how-it-works/malicious-script-detection/).

**Other options / filters**

None.

**Included with**

Customers with Client-Side Security Advanced.

**What should you do if you receive one?**

Review the information in the client-side security dashboard about the detected malicious resources, then update the pages where those resources were detected.

For more information, refer to [Review scripts and connections considered malicious](https://developers.cloudflare.com/client-side-security/detection/review-malicious-scripts/).

Client-side security New Malicious Script Alert

**Who is it for?**

[Client-side security](https://developers.cloudflare.com/client-side-security/) customers who want to receive a notification when Cloudflare classifies JavaScript dependencies in their domain as malicious. For more information, refer to [Malicious script and connection detection](https://developers.cloudflare.com/client-side-security/how-it-works/malicious-script-detection/).

**Other options / filters**

None.

**Included with**

Customers with Client-Side Security Advanced.

**What should you do if you receive one?**

Review the information in the client-side security dashboard about the detected malicious resources, then update the pages where those resources were detected.

For more information, refer to [Review scripts and connections considered malicious](https://developers.cloudflare.com/client-side-security/detection/review-malicious-scripts/).

Malicious resource alerts will only include resources with an _Active_ status. Refer to [Script and connection statuses](https://developers.cloudflare.com/client-side-security/reference/script-statuses/) for more information.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/alerts/","name":"Alerts"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/alerts/alert-types/","name":"Alert types"}}]}
```

---

---
title: Configure an alert
description: Configure scoped or unscoped client-side resource alerts to get notified about relevant client-side changes on your zones.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configure an alert

To configure an alert:

1. In the Cloudflare dashboard, go to the **Notifications** page.  
[ Go to **Notifications** ](https://dash.cloudflare.com/?to=/:account/notifications)
2. Choose **Add** and then select **Client-side security (formerly Page Shield)** in the **Product** dropdown.
3. Select an [alert type](https://developers.cloudflare.com/client-side-security/alerts/alert-types/).
4. Enter the notification name and description.
5. (Optional) If you are a customer with Client-Side Security Advanced, you can [define the zones for which you want to filter alerts](https://developers.cloudflare.com/client-side-security/alerts/#scoped-alerts) in **Rules of these zones**. This option requires that you define [content security rules](https://developers.cloudflare.com/client-side-security/rules/) in the selected zones.
6. Select one or more notification destinations (notification email, webhooks, and connected notification services).
7. Select **Create**.

## Manage alerts

To edit, delete, or disable an alert, go to the **Notifications** page.

[ Go to **Notifications** ](https://dash.cloudflare.com/?to=/:account/notifications) 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/alerts/","name":"Alerts"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/alerts/configure/","name":"Configure an alert"}}]}
```

---

---
title: Content security rules
description: Use content security rules to define the resources (scripts) allowed on your applications.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Content security rules

Note

Only available to customers with Client-Side Security Advanced.

Content security rules (previously known as policies) define which resources your application is allowed to load. They work through Content Security Policy (CSP) directives that Cloudflare adds to your HTTP responses. There are two types of content security rules:

* **Log rules** report resources that fall outside your allowlist without blocking them.
* **Allow rules** block any resource not explicitly listed.

Create [allow rules](#rule-actions) to define an allowlist-based security model. You specify exactly which resources are permitted and everything else is rejected. This approach reduces the attack surface for unwanted third-party scripts in your application.

A content security rule can control both client-side resources monitored by Cloudflare, such as scripts and their connections, and other types of resources. Refer to [Supported CSP directives](https://developers.cloudflare.com/client-side-security/rules/csp-directives/) for details.

Note

Third-party service providers may require specific CSP directives. Refer to your provider's documentation for more information on the CSP directives you need to include in your rule.

## Rule actions

A content security rule can perform one of the following actions:

* **Log**: Cloudflare reports any resources not covered by the rule as [rule violations](https://developers.cloudflare.com/client-side-security/rules/violations/) without blocking them. Use this action to validate a new content security rule before deploying it.
* **Allow**: Cloudflare blocks any resources not explicitly allowed by the rule and logs them as [rule violations](https://developers.cloudflare.com/client-side-security/rules/violations/). Switch to this action after validating a rule with the _Log_ action to avoid blocking essential application resources.

For details on the CSP directives Cloudflare creates for each type of rule action, refer to [How client-side security works](https://developers.cloudflare.com/client-side-security/how-it-works/#headers-related-to-content-security-rules). For more information on the CSP directives supported by content security rules, refer to [Supported CSP directives](https://developers.cloudflare.com/client-side-security/rules/csp-directives/).

### Comparison

| Log rule           | Allow rule                              |                                        |
| ------------------ | --------------------------------------- | -------------------------------------- |
| **CSP header**     | content-security-policy-report-only     | content-security-policy                |
| **Browser action** | Loads all resources                     | Blocks resources not in your allowlist |
| **Violations**     | Reported to Cloudflare without blocking | Logged by Cloudflare after blocking    |
| **Use case**       | Validate a rule before enforcing it     | Enforce a positive security model      |

## Next steps

Refer to the following pages for instructions on creating a content security rule:

* [Create a content security rule in the dashboard](https://developers.cloudflare.com/client-side-security/rules/create-dashboard/)
* [Client-side security API: Create a content security rule](https://developers.cloudflare.com/client-side-security/reference/api/#create-a-content-security-rule)

Shortly after you configure content security rules, the Cloudflare dashboard will start displaying any [violations](https://developers.cloudflare.com/client-side-security/rules/violations/) of those rules.

You can filter client-side security alert notifications according to the content security rules you configured in a zone. These alerts are called [scoped alerts](https://developers.cloudflare.com/client-side-security/alerts/#scoped-alerts).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/rules/","name":"Content security rules"}}]}
```

---

---
title: Create a content security rule in the dashboard
description: Learn how to create a content security rule in the Cloudflare dashboard.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Create a content security rule in the dashboard

Note

Only available to customers with Client-Side Security Advanced.

* [  New dashboard ](#tab-panel-6857)
* [ Old dashboard ](#tab-panel-6858)

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. Select **Create** \> **Content security rules**.
3. Enter a descriptive name for the rule in **Description**.
4. Under **If incoming requests match**, define the scope of the content security rule (or policy). You can use the Expression Builder (specifying one or more values for **Field**, **Operator**, and **Value**) or manually enter an expression using the Expression Editor. For more information, refer to [Edit expressions in the dashboard](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/edit-expressions/).
5. Under **Allow these directives**, select the desired [CSP directives](https://developers.cloudflare.com/client-side-security/rules/csp-directives/) for the content security rule by enabling one or more checkboxes.  
   * To manually enter an allowed source, select **Add source**.  
   * To refresh the displayed sources based on detected resources, select **Refresh suggestions**.  
   Note  
   Cloudflare provides suggestions for **Default**, **Scripts**, and **Connections** directives. For the **Default** directive, suggestions are based on monitored scripts and connections resources.
6. Under **Then take action**, select the desired action:  
   * _Allow_: Enforces the CSP directives configured in the rule, blocking any other resources from being loaded on your website, and logging any [rule violations](https://developers.cloudflare.com/client-side-security/rules/violations/).  
   * _Log_: Logs any content security rule violations without blocking any resources not covered by the rule.
7. To save and deploy your rule, select **Deploy**. If you are not ready to deploy your rule, select **Save as Draft**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com) and select your account and domain.
2. Go to **Security** \> **Client-side security** \> **Rules**.
3. Select **Create rule**.
4. Enter a descriptive name for the rule in **Description**.
5. Under **If incoming requests match**, define the rule scope. You can use the Expression Builder (specifying one or more values for **Field**, **Operator**, and **Value**) or manually enter an expression using the Expression Editor. For more information, refer to [Edit expressions in the dashboard](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/edit-expressions/).
6. Under **Allow these directives**, select the desired [CSP directives](https://developers.cloudflare.com/client-side-security/rules/csp-directives/) for the rule by enabling one or more checkboxes.  
   * To manually enter an allowed source, select **Add source**.  
   * To refresh the displayed sources based on detected resources, select **Refresh suggestions**.  
   Note  
   Cloudflare provides suggestions for **Default**, **Scripts**, and **Connections** directives. For the **Default** directive, suggestions are based on monitored scripts and connections resources.
7. Under **Then take action**, select the desired action:  
   * _Allow_: Enforces the CSP directives configured in the rule, blocking any other resources from being loaded on your website, and logging any [rule violations](https://developers.cloudflare.com/client-side-security/rules/violations/).  
   * _Log_: Logs any content security rule violations without blocking any resources not covered by the rule.
8. To save and deploy your rule, select **Deploy**. If you are not ready to deploy your rule, select **Save as Draft**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/rules/","name":"Content security rules"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/rules/create-dashboard/","name":"Create a content security rule in the dashboard"}}]}
```

---

---
title: Supported CSP directives
description: CSP directives supported by content security rules
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Supported CSP directives

[Content security rules](https://developers.cloudflare.com/client-side-security/rules/) support most Content Security Policy (CSP) directives, covering both monitored and unmonitored resources. You can use a content security rule to control other types of resources besides scripts and their connections, even though Cloudflare is not monitoring these resources.

Each CSP directive can contain multiple values, including:

* Schemes
* Hostnames
* URIs
* Special keywords between single quotes (for example, `'none'`)
* Hashes between single quotes (for example, `'sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC'`)

Hostname and URI values support a `*` wildcard for the leftmost subdomain.

The following table lists the supported CSP directives and special values you can use in content security rules:

| Directive                 | Name in the dashboard     | Supported special values                         | Monitored                                                                                            |
| ------------------------- | ------------------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------- |
| script-src                | Scripts                   | 'none''self''unsafe-inline''unsafe-eval''<HASH>' | [Yes](https://developers.cloudflare.com/client-side-security/detection/monitor-connections-scripts/) |
| connect-src               | Connections               | 'none''self''unsafe-inline''unsafe-eval''<HASH>' | [Yes](https://developers.cloudflare.com/client-side-security/detection/monitor-connections-scripts/) |
| default-src               | Default                   | 'none''self''unsafe-inline''unsafe-eval''<HASH>' | No                                                                                                   |
| img-src                   | Images                    | 'none''self''unsafe-inline''unsafe-eval''<HASH>' | No                                                                                                   |
| style-src                 | Styles                    | 'none''self''unsafe-inline''unsafe-eval''<HASH>' | No                                                                                                   |
| font-src                  | Fonts                     | 'none''self''unsafe-inline''unsafe-eval''<HASH>' | No                                                                                                   |
| object-src                | Objects                   | 'none''self''unsafe-inline''unsafe-eval''<HASH>' | No                                                                                                   |
| media-src                 | Media                     | 'none''self''unsafe-inline''unsafe-eval''<HASH>' | No                                                                                                   |
| child-src                 | Child                     | 'none''self''unsafe-inline''unsafe-eval''<HASH>' | No                                                                                                   |
| form-action               | Form actions              | 'none''self''unsafe-inline''unsafe-eval''<HASH>' | No                                                                                                   |
| worker-src                | Workers                   | 'none''self''unsafe-inline''unsafe-eval''<HASH>' | No                                                                                                   |
| base-uri                  | Base URI                  | 'none''self''unsafe-inline''unsafe-eval''<HASH>' | No                                                                                                   |
| manifest-src              | Manifests                 | 'none''self''unsafe-inline''unsafe-eval''<HASH>' | No                                                                                                   |
| frame-src                 | Frames                    | 'none''self''unsafe-inline''unsafe-eval''<HASH>' | No                                                                                                   |
| frame-ancestors           | Frame ancestors           | 'none''self'                                     | No                                                                                                   |
| upgrade-insecure-requests | Upgrade insecure requests | N/A                                              | No                                                                                                   |

## More resources

For more information on CSP directives and their values, refer to the following resources in the MDN documentation:

* [Content-Security-Policy response header ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy)
* [CSP guide ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/rules/","name":"Content security rules"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/rules/csp-directives/","name":"Supported CSP directives"}}]}
```

---

---
title: Content security rule violations
description: Cloudflare reports any violations to your content security rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Content security rule violations

Note

Only available to customers with Client-Side Security Advanced.

A rule violation occurs when a browser loads a resource that is not covered by one of your [content security rules](https://developers.cloudflare.com/client-side-security/rules/). For log rules, the resource loads normally but is reported. For allow rules, the browser blocks the resource.

Shortly after you configure content security rules, the Cloudflare dashboard will start displaying any violations of those rules. This information is available for rules with any [action](https://developers.cloudflare.com/client-side-security/rules/#rule-actions) (_Allow_ and _Log_).

Information about rule violations is also available via [GraphQL API](#get-rule-violations-via-graphql-api) and [Logpush](#get-rule-violations-via-logpush).

## Review rule violations in the dashboard

To view rule violation information:

* [  New dashboard ](#tab-panel-6859)
* [ Old dashboard ](#tab-panel-6860)

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. (Optional) Filter by **Content security rules**.

* In the Cloudflare dashboard, go to **Security** \> **Client-side security** \> **Rules**.

The displayed information includes the following:

* A sparkline next to the rule name, showing violations in the past seven days.
* For content security rules with associated violations, an expandable details section for each rule, with the top resources present in violation events and a sparkline per top resource.

## Get rule violations via GraphQL API

Use the [Cloudflare GraphQL API](https://developers.cloudflare.com/analytics/graphql-api/) to obtain rule violation information through the following dataset:

* `pageShieldReportsAdaptiveGroups`

You can query the dataset for rule violations that occurred in the past 30 days.

Use [introspection](https://developers.cloudflare.com/analytics/graphql-api/features/discovery/introspection/) to explore the available fields the GraphQL schema. For more information, refer to [Explore the GraphQL schema](https://developers.cloudflare.com/analytics/graphql-api/getting-started/explore-graphql-schema/).

For an introduction to GraphQL querying, refer to [Querying basics](https://developers.cloudflare.com/analytics/graphql-api/getting-started/querying-basics/).

### Example

Example GraphQL query

```

query PageShieldReports(

  $zoneTag: string

  $datetimeStart: Time

  $datetimeEnd: Time

) {

  viewer {

    zones(filter: { zoneTag: $zoneTag }) {

      pageShieldReportsAdaptiveGroups(

        limit: 100

        orderBy: [datetime_ASC]

        filter: { datetime_geq: $datetimeStart, datetime_leq: $datetimeEnd }

      ) {

        avg {

          sampleInterval

        }

        count

        dimensions {

          policyID

          datetime

          datetimeMinute

          datetimeFiveMinutes

          datetimeFifteenMinutes

          datetimeHalfOfHour

          datetimeHour

          url

          urlHost

          host

          resourceType

          pageURL

          action

        }

      }

    }

  }

}


```

[Run in GraphQL API Explorer](https://graphql.cloudflare.com/explorer?query=I4VwpgTgngBACgQwOZgMoAsCWYA2ATAJTAAcB7CAFwGcAKAKBhgBIAvUgOzABVkAuGKhQiZ2SBszwIKYCpgC2aCgkr8u8sOKaTpshQFF2eVeroBKGAG9xAN2wB3SJfGM2nWgDNMOaRH4WYrtx8zIE8SDAAvuZWjLEwxMhoWLiEJOTUAIKSxLLWYADiEKQgxLTOcTA48pgU-ACMAAwN5XHkeJAAQlD8ANraMuoA+hmoAMIAui2xnt6QfjD9umCDKMD8WlIDCqhKlAA0C5tLgzhgaxJH6gZ4kVPRU4wI1uExFXFUCHLEpwCS7D7WBA4B63N6MADGxX+ILw6nYVEwHCoTjBsTIVXBUB+ABEQYxFiZUfjLgoALIiEDSPGHHTqABimDy5PYlLAVGpBIUDPc0jA7GZrPZRJpWzAAAkge4APLuMXFCAckni+XUkAQYHCtU4OWCanoUi64UQNny8HcKDEDTChIoACqBAAMtSEODZBwQREpp64t7bhEgA&variables=N4IgXg9gdgpgKgQwOYgFwgFoHkByBRAfQEkAREAGhABMEAXGWgSwFsYBlWhAJ1rRACYADPwBsAWkHiAjPzhSArKkEBOVABYAHBgrU6DFjDxQqfIaInTZ-KUtWbtAXyA)

Example curl request

Terminal window

```

echo '{ "query":

  "query PageShieldReports($zoneTag: string, $datetimeStart: string, $datetimeEnd: string) {

    viewer {

      zones(filter: {zoneTag: $zoneTag}) {

        pageShieldReportsAdaptiveGroups(limit: 100,  orderBy: [datetime_ASC], filter: {datetime_geq:$datetimeStart, datetime_leq:$datetimeEnd}) {

          avg {

            sampleInterval

          }

          count

          dimensions {

            policyID

            datetime

            datetimeMinute

            datetimeFiveMinutes

            datetimeFifteenMinutes

            datetimeHalfOfHour

            datetimeHour

            url

            urlHost

            host

            resourceType

            pageURL

            action

          }

        }

      }

    }

  }",

  "variables": {

    "zoneTag": "<CLOUDFLARE_ZONE_ID>",

    "datetimeStart": "2023-04-17T11:00:00Z",

    "datetimeEnd": "2023-04-24T12:00:00Z"

  }

}' | tr -d '\n' | curl --silent \

https://api.cloudflare.com/client/v4/graphql \

--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

--header "Content-Type: application/json" \

--data @-


```

## Get rule violations via Logpush

[Cloudflare Logpush](https://developers.cloudflare.com/logs/logpush/) supports pushing logs to storage services, SIEM systems, and log management providers.

Information about rule violations is available in the [page\_shield\_events dataset](https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/zone/page%5Fshield%5Fevents/).

For more information on configuring Logpush jobs, refer to [Logpush](https://developers.cloudflare.com/logs/logpush/) documentation.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/rules/","name":"Content security rules"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/rules/violations/","name":"Content security rule violations"}}]}
```

---

---
title: Client-side security FAQ
description: Answers to common questions about client-side security rules, CSP headers, and monitoring.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Client-side security FAQ

## What happens to CSP HTTP headers set by the origin server when I create a content security rule?

When you create content security rules, Cloudflare will generate content security policy (CSP) directives from those rules based on their configuration:

* Log rules will create CSP directives for the `Content-Security-Policy-Report-Only` HTTP header.
* Allow rules will create CSP directives for the `Content-Security-Policy` HTTP header.

Client-side security only adds new CSP HTTP headers to the response. This means that Cloudflare will keep any `Content-Security-Policy-Report-Only` and `Content-Security-Policy` HTTP headers in the response set by the origin server and it will add separate HTTP headers for the content security rules configured on your Cloudflare zone.

It is recommended that you only have one rule in [allow mode](https://developers.cloudflare.com/client-side-security/rules/#rule-actions) (that is, a content security rule being enforced). If there is more than one `Content-Security-Policy` HTTP header in the response, the most restrictive policy wins. For more information, refer to the [MDN documentation ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy#multiple%5Fcontent%5Fsecurity%5Fpolicies).

## Can I add a `nonce` CSP directive to a content security rule?

Client-side security currently does not support [nonce ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP#nonces) directives in content security rules. Instead, you can use a [hash ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP#hashes) CSP directive. For details on the supported directives and values, refer to [Supported CSP directives](https://developers.cloudflare.com/client-side-security/rules/csp-directives/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/faq/","name":"Client-side security FAQ"}}]}
```

---

---
title: Troubleshooting
description: Resolve common issues with client-side resource monitoring and script detection.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

## Cloudflare does not show any client-side resources after activation

Cloudflare does not collect data on every single page view. Instead, it uses a sampling approach to gather information efficiently. This means that domains with lower traffic might take longer to generate initial reports, as these domains need more page views to accumulate enough samples. To speed up the reporting process, it is recommended that you actively generate traffic to your application after [activating client-side resource monitoring](https://developers.cloudflare.com/client-side-security/get-started/). This will provide Cloudflare with more data to work with, leading to faster report generation.

Other steps you can take to troubleshoot this issue:

* Verify that [client-side resource monitoring is turned on](https://developers.cloudflare.com/client-side-security/get-started/#1-activate-client-side-resource-monitoring).
* After enabling client-side resource monitoring and generating some traffic to your application (at least 100 requests), wait approximately one hour to ensure that Cloudflare has already collected and processed enough data to display in the client-side resource monitoring dashboard.
* Use your browser's dev tools (**Network** tab) to check if the [content-security-policy-report-only HTTP header](https://developers.cloudflare.com/client-side-security/reference/csp-header/) is present.
* Use analytics dashboards to verify if traffic is being proxied by Cloudflare.
* Check if there are duplicate or conflicting Content Security Policy (CSP) headers in responses. Your origin server might be adding CSP headers to the response.

## The dashboard shows scripts and connections that I do not recognize

Scripts often reference other scripts outside your application.

But, if you see unexpected scripts on your resource monitoring dashboard, check them for signs of malicious activity.

## I get warnings in my browser's developer tools related to Content Security Policy (CSP)

Cloudflare uses a Content Security Policy (CSP) report-only directive to gather a list of all scripts running on your application.

Some browsers display scripts being reported as warnings in the console pane of their developer tools. For example:

```

[Report Only] Refused to execute inline script because it violates

the following Content Security Policy directive: "script-src 'none'".


Either the 'unsafe-inline' keyword, a hash ('sha256-RFWPLDbv2BY+rCkDzsE+0fr8ylGr2R2faWMhq4lfEQc='), or a nonce ('nonce-...')

is required to enable inline execution.


```

You can safely ignore these warnings, since they are related to the reports that Cloudflare requires to detect loaded scripts. For more information, refer to [How client-side security works](https://developers.cloudflare.com/client-side-security/how-it-works/).

## I get rule violation reports for a domain I allowlisted

Rule violations reported via CSP's [report-only directive](https://developers.cloudflare.com/client-side-security/reference/csp-header/) do not take into consideration any redirects or redirect HTTP status codes. This is [by design ↗](https://www.w3.org/TR/CSP3/#create-violation-for-request) for security reasons.

Some third-party services you may want to cover in your allow rules perform redirects. An example of such a service is Google Ads, which [does not work well with CSP policies ↗](https://support.google.com/adsense/thread/102839782?hl=en&msgid=103611259).

For example, if you add the `adservice.google.com` domain to an allow rule, you could get rule violation reports for this domain due to redirects to a different domain (not present in your allow rule). In this case, the violation report would still mention the original domain, and not the domain of the redirected destination, which can cause some confusion.

To try to solve this issue, add the domain of the redirected destination to your allow rule. You may need to add several domains to your rule due to redirects.

## I get scoped alerts for hostnames I do not manage on a SaaS root zone

If you operate an [SSL for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) root zone with custom hostnames, and you configured a [scoped alert](https://developers.cloudflare.com/client-side-security/alerts/#scoped-alerts) with a content security rule that uses the `'self'` keyword, you will receive alerts for resources detected across all custom hostnames served under your root zone, not only on your own application surfaces.

This is expected behavior:

* SSL for SaaS applies your root zone's content security rule to every custom hostname served under it.
* The `'self'` keyword in a CSP directive matches the hostname of the request being served. When a custom hostname loads its own scripts, those scripts match `'self'` and the scoped alert fires.

At SaaS scale, this can produce a high volume of alerts across hostnames you do not manage, and makes it difficult to isolate the scope of your own compliance audits (for example, the specific pages where you collect cardholder data).

There is currently no way to scope a content security rule to the root zone only, excluding custom hostnames. If you only need to monitor your own application surfaces, consider one of the following:

* Use a content security rule expression that matches only the specific page paths you control (for example, the request paths where you collect cardholder data).
* Replace `'self'` with an explicit list of hostnames you control. Note that this is rarely feasible at SaaS scale because CSP headers have practical size limits.
* If neither workaround fits, contact your account team to track interest in scoping content security rules to the SaaS root zone only.

## My rule is not triggering (CSP header not added)

If you have configured a content security rule but the expected CSP header is not being added to responses, [Transform Rules](https://developers.cloudflare.com/rules/transform/) may be rewriting the request path before the content security rule is evaluated.

Cloudflare evaluates rules in a [specific order](https://developers.cloudflare.com/ruleset-engine/reference/phases-list/) across different phases. [URL Rewrite Rules](https://developers.cloudflare.com/rules/transform/url-rewrite/) run early in the request lifecycle, while content security rules are evaluated later, during response phases.

This means that if your content security rule is matching incoming requests based on the request URI path (for example, using the field `http.request.uri.path`), the content security rule will evaluate against the rewritten path, not the original URI path requested by the visitor.

### Solution

To fix this issue, choose one of the following approaches:

* **Update the content security rule condition to match the rewritten path**: Change your rule's expression to match the rewritten URI path instead of the original visitor's URI path.
* **Use raw fields to match the original URI path**: Use the [raw.http.request.uri.path](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/raw.http.request.uri.path/) field instead of the [http.request.uri.path](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.request.uri.path/) field in your content security rule expression. [Raw fields](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/?field-category=Raw+fields) preserve the original request values and are not affected by Transform Rules.

When troubleshooting this issue, consider using [Cloudflare Trace](https://developers.cloudflare.com/rules/trace-request/) to verify how the request path changes as it passes through different phases.

## Responses contain duplicate CSP headers

If responses have duplicate `Content-Security-Policy` or `Content-Security-Policy-Report-Only` headers, this is likely caused by having both client-side security and a [response header transform rule](https://developers.cloudflare.com/rules/transform/response-header-modification/) adding the same header type.

Content security rules automatically add CSP headers to responses:

* [Log rules](https://developers.cloudflare.com/client-side-security/rules/#rule-actions) add `Content-Security-Policy-Report-Only` headers.
* [Allow rules](https://developers.cloudflare.com/client-side-security/rules/#rule-actions) add `Content-Security-Policy` headers.

If you have a response header transform rule configured with the **Add** operation for the same header type, both headers will be present in the response.

When browsers encounter multiple CSP headers, they enforce all of them, and the most restrictive policy wins. This can lead to unexpected blocking of legitimate resources.

### Solution

If you need to use Response Header Transform Rules alongside client-side security policies, use the **Set static** or **Set dynamic** operations. These operations replace any existing header value, including headers added by Cloudflare's client-side security. Using these operations will make your transform rule take precedence over client-side security.

Follow these steps to troubleshoot this issue:

1. Use your browser's dev tools (**Network** tab) to inspect the response headers and check for duplicate CSP headers.
2. Review your configured [Response Header Transform Rules](https://developers.cloudflare.com/rules/transform/response-header-modification/) and check if any are using the **Add** operation for `Content-Security-Policy` or `Content-Security-Policy-Report-Only` headers.
3. Change the operation from **Add** to **Set static** or **Set dynamic** if you want the transform rule to override client-side security's CSP headers.
4. Alternatively, disable or adjust the content security rule scope to avoid overlap with your transform rule.

### Recommended patterns

| Scenario                                     | Recommended approach                                                                                                         |
| -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Client-side security manages all CSP headers | Do not create Response Header Transform Rules for CSP headers.                                                               |
| Transform Rule manages all CSP headers       | Use **Set static** or **Set dynamic** operations, and consider excluding the affected paths from your content security rule. |
| Different CSP headers for different paths    | Use content security rule conditions to target specific paths, and avoid overlapping Transform Rules.                        |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: Release notes
description: Track the latest updates and changes to client-side security features.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Release notes

[ Subscribe to RSS ](https://developers.cloudflare.com/client-side-security/release-notes/index.xml)

## 2026-03-25

**Page Shield is now client-side security**

Cloudflare renamed Page Shield to client-side security. Cloudflare dashboard users still using the previous application security navigation in the dashboard can find the new client-side security section in **Security** \> **Client-side security**.  
Additionally, Page Shield policies are now called content security rules. This name matches the terminology already used in the new [application security dashboard](https://developers.cloudflare.com/security/).

## 2026-03-03

**Deprecated code behavior analysis scores**

Code behavior analysis scores have been removed from the malicious script details. The updated GNN and LLM-based detection approach has proven significantly more effective at identifying true positives, making the separate behavior analysis scores redundant.

Malicious code analysis scores and threat intelligence remain available for reviewing detected scripts. For more information, refer to [Review resources considered malicious](https://developers.cloudflare.com/client-side-security/detection/review-malicious-scripts/).

## 2026-03-03

**LLM-assisted false positive reduction for malicious script detection**

Page Shield now includes an additional machine learning step, utilizing an LLM powered by Workers AI, to assist in analyzing the JavaScript code of scripts loaded by your website visitors. This enhancement specifically helps reduce the false positive rate of our detection engines, focusing your attention on true positives.

Cloudflare uses open-source models for this analysis, and customer data is not used to train these models. For more information, refer to [Malicious script and connection detection](https://developers.cloudflare.com/client-side-security/how-it-works/malicious-script-detection/).

## 2025-10-08

**Updated machine learning (ML) model**

The latest ML model has been deployed to all Page Shield add-on customers with better classification precision. Scripts with false positive classification may have a different pattern than the previous model deployment.

## 2025-09-12

**Scoped alerts now support policies in log mode**

[Scoped alerts](https://developers.cloudflare.com/client-side-security/alerts/) now take into account your Page Shield policies deployed in log mode. This allows you to simulate an end-to-end workflow before switching your policies to [allow mode](https://developers.cloudflare.com/client-side-security/rules/#rule-actions).

## 2025-05-20

**Updated machine learning (ML) model**

The latest ML model has been deployed to all Page Shield add-on customers with better classification precision. Scripts with false positive classification may have a different pattern than the previous model deployment.

## 2025-05-09

**Reports from browser extension injected resources are filtered out**

Script and connection reports caused by browser extension injections are now filtered out, helping you focus on managing application dependencies.

## 2024-12-02

**Alerts based on customer-defined policies**

You can now scope all of Page Shield's alert types to selected zones and their associated policies, alerting only on the resources that have been explicitly allowed.

## 2024-09-30

**New machine learning (ML) scores for detected scripts**

In addition to the global integrity score, Page Shield now provides individual script scores (from 1 to 99) for the following malicious code detections: Magecart, Crypto mining, and Malware.

## 2024-09-18

**Page Shield's script monitor now available in Free plan**

The Page Shield's script monitor feature is now available to all users, including users in the Free plan.

## 2024-09-18

**Page Shield policy changes now available in audit logs**

Cloudflare [Audit Logs](https://developers.cloudflare.com/fundamentals/account/account-security/review-audit-logs/) now include entries for any changes to Page Shield's policies.

## 2024-06-18

**Cookie Monitor now available**

Page Shield now captures HTTP cookies set and used by your web application. The [list of detected cookies](https://developers.cloudflare.com/client-side-security/detection/monitor-connections-scripts/) in available in the Cloudflare dashboard or via API.

## 2024-06-14

**Added filter operators for scripts and connections**

You can now filter scripts and connections in the Cloudflare dashboard using the `does not contain` operator. Pages associated with scripts and connections can be filtered by `includes`, `starts with`, and `ends with`.

## 2024-04-26

**Suggestions for the default directive**

When creating a policy in the dashboard, default directive aggregates suggestions of monitored scripts and connections data, enabling defining default directive easier.

## 2024-04-04

**Individual threat intelligence categories**

Instead of aggregating categories of URL and domain data from threat intelligence, they are now listed per type.

## 2024-03-21

**Increase allowed length per policy**

Now each policy supports up to 6,000 characters.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/release-notes/","name":"Release notes"}}]}
```

---

---
title: Deploy content security rules in production
description: Safe practices for deploying and updating content security rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Deploy content security rules in production

Note

Only available to customers with Client-Side Security Advanced.

Follow the practices on this page when deploying or updating [content security rules](https://developers.cloudflare.com/client-side-security/rules/) in a production environment. Applying rule changes without a validation period can block legitimate resources and disrupt your application for end users.

## Update rules safely

When updating content security rules in production, avoid the following:

* Do not edit an existing rule directly in production without testing first.
* Do not change a rule action from _Log_ to _Allow_ without a validation period.
* Do not delete all rules at once.

Instead, follow these practices:

* Test changes in a staging environment before applying them in production.
* Use the _Log_ [rule action](https://developers.cloudflare.com/client-side-security/rules/#rule-actions) for at least seven days before switching to _Allow_.
* Update one rule at a time.
* Monitor [rule violations](https://developers.cloudflare.com/client-side-security/rules/violations/) for 24 hours after each change.
* Document a rollback procedure before making changes.

## Pre-enforcement checklist

Complete the following checklist before switching a content security rule from _Log_ to _Allow_:

* The rule was tested in _Log_ mode for a minimum of seven days.
* Reviewed all [rule violations](https://developers.cloudflare.com/client-side-security/rules/violations/) and confirmed there are no unexpected blocks.
* Added all legitimate third-party resources to the rule allowlist.
* Tested the application on all major browsers (Chrome, Firefox, Safari, Edge).
* Configured [alerts](https://developers.cloudflare.com/client-side-security/alerts/) for rule violations.
* There is a documented rollback procedure that is ready to execute.

Warning

Switching a rule from _Log_ to _Allow_ without completing this checklist may block resources required by your application. This will directly affect your end users.

## Rollback a rule change

If a rule change causes unexpected violations or blocks legitimate resources:

1. Switch the rule action back to _Log_ to stop blocking resources immediately.
2. Review the [rule violations](https://developers.cloudflare.com/client-side-security/rules/violations/) to identify which resources were blocked.
3. Update the rule to include any missing resources.
4. Repeat the validation process before switching back to _Allow_ (blocks resources not present in the allowlist).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/best-practices/","name":"Best practices"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/best-practices/deploy-rules-in-production/","name":"Deploy content security rules in production"}}]}
```

---

---
title: Handle a client-side resource alert
description: If you receive a client-side resource alert, sometimes you need to perform some manual investigation to confirm the nature of the script. Use the guidance provided in this page as a starting point for your investigation.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Handle a client-side resource alert

If you receive a [client-side resource alert](https://developers.cloudflare.com/client-side-security/alerts/alert-types/), sometimes you need to perform some manual investigation to confirm the nature of the script. Use the guidance provided in this page as a starting point for your investigation.

## 1\. Understand what triggered the alert

Start by identifying the [detection system](https://developers.cloudflare.com/client-side-security/how-it-works/malicious-script-detection/) that triggered the alert. A link is provided in the alert that will send you directly to the Cloudflare dashboard to the relevant resource that needs reviewing. Alternatively, do the following:

1. Navigate to the client-side resources page:  
   * [  New dashboard ](#tab-panel-6823)  
   * [ Old dashboard ](#tab-panel-6824)  
   1. In the Cloudflare dashboard, go to the **Web assets** page.  
   [ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)  
   2. Select the **Client-side resources** tab.  
   1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.  
   2. Go to **Security** \> **Client-side security**.
2. Select **Scripts** or **Connections** and search for the resource mentioned on the alert you received.
3. Select **Details** next to the resource you identified. The example screenshot below shows a malicious script resource.  
![Dialog box showing the details of a script considered malicious.](https://developers.cloudflare.com/_astro/handle-alert-malicious-script-example.DqLS6vtx_ZFsQFA.webp)

The details page will specify which detection system triggered the alert. Check the values of the following fields:

* **Malicious code**
* **Malicious URL**
* **Malicious domain**

Different detection mechanisms may consider the script malicious at the same time. This increases the likelihood of the detection not being a false positive.

## 2\. Find the page where the resource was detected

If you received an alert for a potentially malicious script:

1. Navigate to the page on your website that is loading the script or performing the connection. Open a browser and navigate to one of the URLs in the **Page URLs** field (shown in the script details dialog box).
2. Open the browser's developer tools to confirm that the script is being loaded. You can check this in the developer tools' **Network** tab, searching for the script name, URL, or hostname.

If you received an alert for a potentially malicious connection:

1. Go to the page on your website where the connection that triggered the alert is being made. Open a browser and go to one of the URLs specified in the **Page URLs** field (shown in the connection details dialog box).
2. Open the browser's developer tools to confirm that the connection is being made. You can check this in the developer tools' **Network** tab, searching for the target hostname of the connection.

If you find the script or connection, this means the script is being loaded (or the connection is being established) for all website visitors — proceed to [step 3](#3-check-the-script-reputation).

If you do not find the script being loaded or the connection being made, this could mean one of the following:

* The script is being loaded (or the connection is being made) by visitors' browser extensions.
* Your current state will not load the script or make the connection. Complex applications might load scripts and establish connections based on state.
* You are not in the correct geographic location (or similar condition).
* The attacker is only loading the script or making the connection for a percentage of visitors or visitors with specific browsers/signatures.

In this case, in addition to the steps indicated below, the best approach is:

* From a safe virtual environment, use online search tools and search for the given resource. Review results and resource metadata, for example domain registration details;
* If in doubt, scan the application codebase for the resource and if found, clarify the purpose.

## 3\. Check the script reputation

If Cloudflare considers the resource’s domain a "malicious domain", it is likely that the domain does not have a good reputation. The domain may be known for hosting malware or for being used for phishing attacks. Usually, reviewing the domain/hostname is sufficient to understand why you received the alert. You can use tools like Cloudflare's [Security Center Investigate ↗](https://dash.cloudflare.com/?to=/:account/security-center/investigate) platform to help with this validation.

If Cloudflare's internal systems classified the script as containing "malicious code", external tools may not confirm the detection you got from Cloudflare, since the machine learning (ML) model being used is Cloudflare-specific technology.

If you believe that Cloudflare's classification is a false positive, contact your account team so that we can further improve client-side security's underlying technology.

## 4\. (Optional) Analyze the script content

You could use a virtual machine to perform some of the following analysis:

1. Open the script URL and get the script source code. If the script is obfuscated or encoded, this could be a sign that the script is malicious.
2. Scan the script source code for any hostnames or IP addresses.
3. For each hostname or IP address you identified, use Cloudflare's Security Center Investigate platform to look up threat information and/or search online for potential Indicators of Compromise.

---

## Conclusion

If a resource which triggered a malicious resource alert:

* Is actively present in your application
* Is being loaded from a malicious host or IP address, or has malicious code
* Has malicious hostnames or IP addresses in its source code, which may be obfuscated/encoded

You should investigate further, since these indicators can be a sign of an ongoing active compromise.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/best-practices/","name":"Best practices"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/best-practices/handle-an-alert/","name":"Handle a client-side resource alert"}}]}
```

---

---
title: Monitor resources and cookies
description: View and filter scripts, connections, and cookies detected on your domain.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Monitor resources and cookies

Once you [activate client-side security's resource monitoring](https://developers.cloudflare.com/client-side-security/get-started/), the main client-side resources dashboard will show which resources (scripts and connections) are running on your domain, as well as the cookies recently detected in HTTP traffic.

If you notice unexpected scripts or connections on the dashboard, check them for signs of malicious activity. Customers with Client-Side Security Advanced will have their [connections and scripts classified as potentially malicious](https://developers.cloudflare.com/client-side-security/how-it-works/malicious-script-detection/) based on threat feeds. You should also check for any new or unexpected cookies.

Notes

* Users in Free and Pro plans only have access to script monitoring.
* If you recently activated client-side resource monitoring, you may see a delay in reporting.

## Use the client-side resources dashboards

To review the resources detected by Cloudflare:

1. Go to the client-side resources page:  
   * [  New dashboard ](#tab-panel-6825)  
   * [ Old dashboard ](#tab-panel-6826)  
   1. In the Cloudflare dashboard, go to the **Web assets** page.  
   [ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)  
   2. Select the **Client-side resources** tab.  
   1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.  
   2. Go to **Security** \> **Client-side security**.
2. Review the list of scripts, connections, and cookies for your domain, depending on your Cloudflare plan. To apply a filter, select **Add filter** and use one or more of the available options.  
Available filters  
   * **Status**: Filter scripts or connections by [status](https://developers.cloudflare.com/client-side-security/reference/script-statuses/).  
   * **Script URL**: Filter scripts by their URL.  
   * **Connection URL**: Filter connections by their target URL. Depending on your [configuration](https://developers.cloudflare.com/client-side-security/reference/settings/#connection-target-details), it may search only by target hostname.  
   * **Seen on host**: Look for scripts appearing on specific hostnames, or connections made in a specific hostname.  
   * **Seen on page** (requires a Business or Enterprise plan): Look for scripts appearing in a specific page, or for connections made in a specific page. Searches the first page where the script was loaded (or where the connection was made) and the latest occurrences list.  
   * **Type**: Filter cookies according to their type: first-party cookies or unknown.  
   * Cookie property: Filter by a cookie property such as **Name**, **Domain**, **Path**, **Same site**, **HTTP only**, and **Secure**.
3. Depending on your plan, you may be able to [view the details of each item](#view-details).

## View all reported scripts or connections

The All Reported Connections and All Reported Scripts dashboards show all the detected resources including infrequent or inactive ones, reported in the last 30 days. After 30 days without any report, Cloudflare will delete information about a previously reported resource, and it will no longer appear in any of the dashboards.

1. Go to the client-side resources page:  
   * [  New dashboard ](#tab-panel-6827)  
   * [ Old dashboard ](#tab-panel-6828)  
   1. In the Cloudflare dashboard, go to the **Web assets** page.  
   [ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)  
   2. Select the **Client-side resources** tab.  
   1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.  
   2. Go to **Security** \> **Client-side security**.
2. Select **Scripts** or **Connections**.
3. Select **View all scripts** or **View all connections**.
4. Review the information displayed in the dashboard.

You can filter the data in these dashboards using different criteria, and print a report with the displayed records.

## View details

Note

Only available to customers on Business and Enterprise plans.

1. Go to the client-side resources page:  
   * [  New dashboard ](#tab-panel-6829)  
   * [ Old dashboard ](#tab-panel-6830)  
   1. In the Cloudflare dashboard, go to the **Web assets** page.  
   [ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)  
   2. Select the **Client-side resources** tab.  
   1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.  
   2. Go to **Security** \> **Client-side security**.
2. Select **Scripts**, **Connections**, or **Cookies** (the available options depend on your plan).
3. Next to a script, connection, or cookie in the list, select **Details**.  
Script and connection details  
   * **Last seen**: How long ago the resource was last detected (in the last 30 days).  
   * **First seen at**: The date and time when the resource was first detected.  
   * **Seen on host**: The host where the script is being loaded or the connection is being made.  
   * **Seen on pages**: The most recent pages where the resource was detected (up to 10 pages).  
   * **First seen on**: The page where the resource was first detected.  
The script details also include the last 10 script versions detected by client-side security.  
Note  
The **Hash** value shown in the script details for each script version is an internal identifier. This differs from the file content hash defined by [Subresource Integrity (SRI) ↗](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource%5FIntegrity) that is required to be used in [content security rules](https://developers.cloudflare.com/client-side-security/rules/).  
Cookie details  
   * **Type**: A cookie can have the following types:  
         * **First-party**: Cookies set by the origin server through a `set-cookie` HTTP response header.  
         * **Unknown**: All other detected cookies.  
   * **Domain**: The value of the `Domain` cookie attribute. When not set or unknown, this value is derived from the host.  
   * **Path**: The value of the `Path` cookie attribute. When not set or unknown, this value is derived from the most recent page where the cookie was detected.  
   * **Last seen**: How long ago the resource was last detected (in the last 30 days).  
   * **First seen at**: The date and time when the cookie was first detected.  
   * **Seen on host**: The host where the cookie was first detected.  
   * **Seen on pages**: The most recent pages where the cookie was detected (up to 10 pages).  
   * Additional cookie attributes (only available with Client-Side Security Advanced):  
         * **Max age**: The value of the `Max-Age` cookie attribute.  
         * **Expires**: The value of the `Expires` cookie attribute.  
         * **Lifetime**: The approximate cookie lifetime, based on the `Max-Age` and `Expires` cookie attributes.  
         * **HTTP only**: The value of the `HttpOnly` cookie attribute.  
         * **Secure**: The value of the `Secure` cookie attribute.  
         * **Same site**: The value of the `SameSite` cookie attribute.  
Except for **Domain** and **Path**, [standard cookie attributes ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) are only available for first-party cookies, where Cloudflare detected the `set-cookie` HTTP response header in HTTP traffic.

## Export data

Note

Only available to customers with Client-Side Security Advanced.

Use this feature to extract data for review and annotation. The data in the exported file will honor any filters you configure in the dashboard.

To export script, connection, or cookie information in CSV format:

1. Go to the client-side resources page:  
   * [  New dashboard ](#tab-panel-6831)  
   * [ Old dashboard ](#tab-panel-6832)  
   1. In the Cloudflare dashboard, go to the **Web assets** page.  
   [ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)  
   2. Select the **Client-side resources** tab.  
   1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.  
   2. Go to **Security** \> **Client-side security**.
2. Select **Scripts**, **Connections**, or **Cookies**.
3. (Optional) Apply any filters to the displayed data.
4. Select **Download CSV**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/detection/","name":"Detection"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/detection/monitor-connections-scripts/","name":"Monitor resources and cookies"}}]}
```

---

---
title: Review changed scripts
description: Learn how to review scripts on your domain after receiving a code change alert.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Review changed scripts

Note

Only available to customers with Client-Side Security Advanced.

Cloudflare analyzes the JavaScript dependencies in the pages of your domain over time.

You can configure a notification for [code change alerts](https://developers.cloudflare.com/client-side-security/alerts/alert-types/#code-change-alert) to receive a daily notification about changed scripts in your domain.

When you receive such a notification:

1. Go to the client-side resources page:  
   * [  New dashboard ](#tab-panel-6833)  
   * [ Old dashboard ](#tab-panel-6834)  
   1. In the Cloudflare dashboard, go to the **Web assets** page.  
   [ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)  
   2. Select the **Client-side resources** tab.  
   1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.  
   2. Go to **Security** \> **Client-side security**.
2. Check the details of each changed script and validate if it is an expected change.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/detection/","name":"Detection"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/detection/review-changed-scripts/","name":"Review changed scripts"}}]}
```

---

---
title: Review resources considered malicious
description: Learn how to review scripts and connections that Cloudflare's client-side security considered malicious.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Review resources considered malicious

Note

Domain-based threat intelligence is available to all customers. Malicious code analysis and URL-based threat intelligence require Client-Side Security Advanced.

Cloudflare displays scripts and connections considered malicious at the top of the dashboard lists, so that you can quickly identify those resources, review them, and take action.

## Review malicious scripts

To review the scripts considered malicious:

1. Go to the client-side resources page:  
   * [  New dashboard ](#tab-panel-6835)  
   * [ Old dashboard ](#tab-panel-6836)  
   1. In the Cloudflare dashboard, go to the **Web assets** page.  
   [ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)  
   2. Select the **Client-side resources** tab.  
   1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.  
   2. Go to **Security** \> **Client-side security**.
2. Select the **Scripts** tab.
3. Select **Details** for each script considered malicious. The script details will contain:  
   * **Malicious code analysis**: Scores between 1-99 classifying how malicious the current script version is, where 1 means definitely malicious and 99 means definitely not malicious.  
   * **Threat intelligence**: Whether the script URL and/or domain is known to be malicious according to threat intelligence feeds. If the script is considered malicious according to the feeds, the dashboard will show a list of associated threat [categories](https://developers.cloudflare.com/client-side-security/how-it-works/malicious-script-detection/#malicious-script-and-connection-categories). If threat intelligence feeds do not have any information about the script URL or domain, the dashboard will show **Not present**.  
The script details also include the last 10 script versions detected by Cloudflare.  
Note  
The **Hash** value shown in the script details for each script version is an internal identifier. This differs from the file content hash defined by [Subresource Integrity (SRI) ↗](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource%5FIntegrity) that is required to be used in [content security rules](https://developers.cloudflare.com/client-side-security/rules/).  
For more information, refer to [Malicious script and connection detection](https://developers.cloudflare.com/client-side-security/how-it-works/malicious-script-detection/).
4. Based on the displayed information, and with the help of the [last seen/first seen fields in the script details](https://developers.cloudflare.com/client-side-security/detection/monitor-connections-scripts/#view-details), review and update the pages where the malicious script was detected.

You can configure alerts for detected malicious scripts. Refer to [Alerts](https://developers.cloudflare.com/client-side-security/alerts/) for more information.

## Review malicious connections

To review the connections considered malicious:

1. Go to the client-side resources page:  
   * [  New dashboard ](#tab-panel-6837)  
   * [ Old dashboard ](#tab-panel-6838)  
   1. In the Cloudflare dashboard, go to the **Web assets** page.  
   [ Go to **Web assets** ](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)  
   2. Select the **Client-side resources** tab.  
   1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.  
   2. Go to **Security** \> **Client-side security**.
2. Select **Connections**.
3. Select **Details** for each connection considered malicious. The connection details will contain:  
   * **URL match**: Whether the connection's target URL is known to be malicious according to threat intelligence feeds. This field requires that you configure client-side security to analyze the [full URI](https://developers.cloudflare.com/client-side-security/reference/settings/#connection-target-details) of outgoing connections.  
   * **Domain match**: Whether the connection's target domain is known to be malicious according to threat intelligence feeds.  
   * **Category**: The categorization of the connection considered malicious according to threat intelligence feeds.  
For more information, refer to [Malicious script and connection detection](https://developers.cloudflare.com/client-side-security/how-it-works/malicious-script-detection/).
4. Based on the displayed information, and with the help of the [last seen/first seen fields in the connection details](https://developers.cloudflare.com/client-side-security/detection/monitor-connections-scripts/#view-details), review and update the pages where the malicious connection was detected.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/detection/","name":"Detection"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/detection/review-malicious-scripts/","name":"Review resources considered malicious"}}]}
```

---

---
title: Client-side security API
description: Manage resource monitoring, settings, and detected scripts using the client-side security API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Client-side security API

You can enable and disable client-side security's resource monitoring, configure settings, and fetch information about detected scripts and connections using the [client-side security API](https://developers.cloudflare.com/api/resources/page%5Fshield/methods/get/) (formerly known as Page Shield API).

To authenticate API requests you need an [API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/). For more information on the required API token permissions, refer to [Roles and permissions](https://developers.cloudflare.com/client-side-security/reference/roles-and-permissions/).

Note

Refer to [API deprecations](https://developers.cloudflare.com/fundamentals/api/reference/deprecations/) for details on client-side security API changes.

## Endpoints

You can obtain the complete endpoint by appending the [client-side security API](https://developers.cloudflare.com/api/resources/page%5Fshield/methods/get/) endpoints to the Cloudflare API base URL:

```

https://api.cloudflare.com/client/v4


```

The `{zone_id}` argument is the zone ID (a hexadecimal string). You can find this value in the Cloudflare dashboard or using the Cloudflare API's [/zones endpoint](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/).

The `{script_id}` argument is the script ID (a hexadecimal string). This value is included in the response of the [List client-side security scripts](https://developers.cloudflare.com/api/resources/page%5Fshield/subresources/scripts/methods/list/) operation for every detected script.

The `{connection_id}` argument is the connection ID (a hexadecimal string). This value is included in the response of the List client-side security connections API operation for every detected connection.

The following table summarizes the available operations:

| Operation                                                                                                                                     | Method + URL stub                                              | Notes                                                            |
| --------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------- |
| [Get client-side security settings](https://developers.cloudflare.com/api/resources/page%5Fshield/methods/get/)                               | GET zones/{zone\_id}/page\_shield                              | Fetch client-side security settings (including the status).      |
| [Update client-side security settings](https://developers.cloudflare.com/api/resources/page%5Fshield/methods/update/)                         | PUT zones/{zone\_id}/page\_shield                              | Update client-side security settings.                            |
| [List client-side security scripts](https://developers.cloudflare.com/api/resources/page%5Fshield/subresources/scripts/methods/list/)         | GET zones/{zone\_id}/page\_shield/scripts                      | Fetch a list of detected scripts.                                |
| [Get a client-side security script](https://developers.cloudflare.com/api/resources/page%5Fshield/subresources/scripts/methods/get/)          | GET zones/{zone\_id}/page\_shield/scripts/{script\_id}         | Fetch the details of a script.                                   |
| [List client-side security connections](https://developers.cloudflare.com/api/resources/page%5Fshield/subresources/connections/methods/list/) | GET zones/{zone\_id}/page\_shield/connections                  | Fetch a list of detected connections.                            |
| [Get a client-side security connection](https://developers.cloudflare.com/api/resources/page%5Fshield/subresources/connections/methods/get/)  | GET zones/{zone\_id}/page\_shield/connections/{connection\_id} | Fetch the details of a connection.                               |
| [List client-side security cookies](https://developers.cloudflare.com/api/resources/page%5Fshield/subresources/cookies/methods/list/)         | GET zones/{zone\_id}/page\_shield/cookies                      | Fetch a list of detected cookies.                                |
| [Get a client-side security cookie](https://developers.cloudflare.com/api/resources/page%5Fshield/subresources/cookies/methods/get/)          | GET zones/{zone\_id}/page\_shield/cookies/{cookie\_id}         | Fetch the details of a cookie.                                   |
| [List content security rules](https://developers.cloudflare.com/api/resources/page%5Fshield/subresources/policies/methods/list/)              | GET zones/{zone\_id}/page\_shield/policies                     | Fetch a list of all configured content security rules.           |
| [Get a content security rule](https://developers.cloudflare.com/api/resources/page%5Fshield/subresources/policies/methods/get/)               | GET zones/{zone\_id}/page\_shield/policies/{policy\_id}        | Fetch the details of a content security rule.                    |
| [Create a content security rule](https://developers.cloudflare.com/api/resources/page%5Fshield/subresources/policies/methods/create/)         | POST zones/{zone\_id}/page\_shield/policies                    | Creates a content security rule with the provided configuration. |
| [Update a content security rule](https://developers.cloudflare.com/api/resources/page%5Fshield/subresources/policies/methods/update/)         | PUT zones/{zone\_id}/page\_shield/policies/{policy\_id}        | Updates an existing content security rule.                       |
| [Delete a content security rule](https://developers.cloudflare.com/api/resources/page%5Fshield/subresources/policies/methods/delete/)         | DELETE zones/{zone\_id}/page\_shield/policies/{policy\_id}     | Deletes an existing content security rule.                       |

## API notes

The malicious script classification (`Malicious` or `Not malicious`) is not directly available in the API. To determine this classification, compare the script's `js_integrity_score` value with the classification threshold, which is currently set to 10\. Scripts with a score value lower than the threshold are considered malicious.

## Common API calls

### Get client-side security settings

This example obtains the current settings of Cloudflare's client-side security, including the status (enabled/disabled).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Page Shield`
* `Domain Page Shield Read`
* `Domain Page Shield`
* `Page Shield Read`
* `Zone Settings Write`
* `Zone Settings Read`

Get Page Shield settings

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/page_shield" \

  --request GET \

  --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \

  --header "X-Auth-Key: $CLOUDFLARE_API_KEY"


```

```

{

  "result": {

    "enabled": true,

    "updated_at": "2023-05-14T11:47:55.677555Z",

    "use_cloudflare_reporting_endpoint": true,

    "use_connection_url_path": false

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

### Enable client-side security

This example enables Cloudflare's client-side security in the specified zone.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Page Shield`
* `Domain Page Shield`
* `Zone Settings Write`

Update Page Shield settings

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/page_shield" \

  --request PUT \

  --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \

  --header "X-Auth-Key: $CLOUDFLARE_API_KEY" \

  --json '{

    "enabled": true

  }'


```

```

{

  "result": {

    "enabled": true,

    "updated_at": "2023-05-14T11:50:41.756996Z"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

### Fetch list of detected scripts

This `GET` request fetches a list of scripts detected by Cloudflare's client-side security on hostname `example.net`, requesting the first page with 15 items per page. The URL query string includes filtering and paging parameters.

By default, the response will only include scripts with `active` status when you do not specify a `status` filter parameter in the URL query string.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Page Shield`
* `Domain Page Shield Read`
* `Domain Page Shield`
* `Page Shield Read`
* `Zone Settings Write`
* `Zone Settings Read`

List Page Shield scripts

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/page_shield/scripts?hosts=example.net&page=1&per_page=15" \

  --request GET \

  --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \

  --header "X-Auth-Key: $CLOUDFLARE_API_KEY"


```

```

{

  "result": [

    {

      "id": "8337233faec2357ff84465a919534e4d",

      "url": "https://malicious.example.com/badscript.js",

      "added_at": "2023-05-18T10:51:10.09615Z",

      "first_seen_at": "2023-05-18T10:51:08Z",

      "last_seen_at": "2023-05-22T09:57:54Z",

      "host": "example.net",

      "domain_reported_malicious": false,

      "url_reported_malicious": true,

      "malicious_url_categories": ["Malware"],

      "first_page_url": "http://malicious.example.com/page_one.html",

      "status": "active",

      "url_contains_cdn_cgi_path": false,

      "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",

      "js_integrity_score": 10,

      "obfuscation_score": 10,

      "dataflow_score": 8,

      "malware_score": 8,

      "cryptomining_score": 9,

      "magecart_score": 8,

      "fetched_at": "2023-05-21T16:58:07Z"

    }

    // (...)

  ],

  "success": true,

  "errors": [],

  "messages": [],

  "result_info": {

    "page": 1,

    "per_page": 15,

    "count": 15,

    "total_count": 24,

    "total_pages": 2

  }

}


```

Some fields displayed in the example response may not be available, depending on your Cloudflare plan.

For details on the available filtering, paging, and sorting parameters, refer to the [API reference](https://developers.cloudflare.com/api/resources/page%5Fshield/subresources/scripts/methods/list/).

### Fetch list of infrequently reported scripts

This `GET` request fetches a list of infrequently reported scripts on hostname `example.net`, requesting the first page with 15 items per page. The URL query string includes filtering and paging parameters.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Page Shield`
* `Domain Page Shield Read`
* `Domain Page Shield`
* `Page Shield Read`
* `Zone Settings Write`
* `Zone Settings Read`

List Page Shield scripts

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/page_shield/scripts?hosts=example.net&page=1&per_page=15&status=infrequent" \

  --request GET \

  --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \

  --header "X-Auth-Key: $CLOUDFLARE_API_KEY"


```

```

{

  "result": [

    {

      "id": "83c8da2267394ce8465b74c299658fea",

      "url": "https://scripts.example.com/anotherbadscript.js",

      "added_at": "2023-05-17T13:16:03.419619Z",

      "first_seen_at": "2023-05-17T13:15:23Z",

      "last_seen_at": "2023-05-18T09:05:20Z",

      "host": "example.net",

      "domain_reported_malicious": false,

      "url_reported_malicious": false,

      "first_page_url": "http://malicious.example.com/page_one.html",

      "status": "infrequent",

      "url_contains_cdn_cgi_path": false,

      "hash": "9245aad577e846dd9b990b1b32425a3fae4aad8b8a28441a8b80084b6bb75a45",

      "js_integrity_score": 48,

      "obfuscation_score": 49,

      "dataflow_score": 45,

      "malware_score": 45,

      "cryptomining_score": 37,

      "magecart_score": 49,

      "fetched_at": "2023-05-18T03:58:07Z"

    }

    // (...)

  ],

  "success": true,

  "errors": [],

  "messages": [],

  "result_info": {

    "page": 1,

    "per_page": 15,

    "count": 15,

    "total_count": 17,

    "total_pages": 2

  }

}


```

Some fields displayed in the example response may not be available, depending on your Cloudflare plan.

For details on the available filtering, paging, and sorting parameters, refer to the [API reference](https://developers.cloudflare.com/api/resources/page%5Fshield/subresources/scripts/methods/list/).

### Get details of a detected script

This `GET` request obtains the details of a script detected by Cloudflare's client-side security with script ID `8337233faec2357ff84465a919534e4d`.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Page Shield`
* `Domain Page Shield Read`
* `Domain Page Shield`
* `Page Shield Read`
* `Zone Settings Write`
* `Zone Settings Read`

Get a Page Shield script

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/page_shield/scripts/8337233faec2357ff84465a919534e4d" \

  --request GET \

  --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \

  --header "X-Auth-Key: $CLOUDFLARE_API_KEY"


```

```

{

  "result": {

    "id": "8337233faec2357ff84465a919534e4d",

    "url": "https://malicious.example.com/badscript.js",

    "added_at": "2023-05-18T10:51:10.09615Z",

    "first_seen_at": "2023-05-18T10:51:08Z",

    "last_seen_at": "2023-05-22T09:57:54Z",

    "host": "example.net",

    "domain_reported_malicious": false,

    "url_reported_malicious": true,

    "malicious_url_categories": ["Malware"],

    "first_page_url": "http://malicious.example.com/page_one.html",

    "status": "active",

    "url_contains_cdn_cgi_path": false,

    "hash": "9245aad577e846dd9b990b1b32425a3fae4aad8b8a28441a8b80084b6bb75a45",

    "js_integrity_score": 48,

    "obfuscation_score": 49,

    "dataflow_score": 45,

    "malware_score": 42,

    "cryptomining_score": 32,

    "magecart_score": 44,

    "fetched_at": "2023-05-21T16:58:07Z",

    "page_urls": [

      "http://malicious.example.com/page_two.html",

      "http://malicious.example.com/page_three.html",

      "http://malicious.example.com/page_four.html"

    ],

    "versions": [

      {

        "hash": "9245aad577e846dd9b990b1b32425a3fae4aad8b8a28441a8b80084b6bb75a45",

        "js_integrity_score": 48,

        "obfuscation_score": 49,

        "dataflow_score": 45,

        "malware_score": 42,

        "cryptomining_score": 32,

        "magecart_score": 44,

        "fetched_at": "2023-05-21T16:58:07Z"

      }

    ]

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

Some fields displayed in the example response may not be available, depending on your Cloudflare plan.

### Fetch list of detected connections

This `GET` request fetches a list of connections detected by Cloudflare's client-side security, requesting the first page with 15 items per page.

By default, the response will only include connections with `active` status when you do not specify a `status` filter parameter in the URL query string.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Page Shield`
* `Domain Page Shield Read`
* `Domain Page Shield`
* `Page Shield Read`
* `Zone Settings Write`
* `Zone Settings Read`

List Page Shield connections

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/page_shield/connections?page=1&per_page=15" \

  --request GET \

  --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \

  --header "X-Auth-Key: $CLOUDFLARE_API_KEY"


```

```

{

  "result": [

    {

      "id": "0a7bb628776f4e50a50d8594c4a01740",

      "url": "https://malicious.example.com",

      "added_at": "2022-09-18T10:51:10.09615Z",

      "first_seen_at": "2022-09-18T10:51:08Z",

      "last_seen_at": "2022-09-02T09:57:54Z",

      "host": "example.net",

      "domain_reported_malicious": true,

      "malicious_domain_categories": ["Malware", "Spyware"],

      "url_reported_malicious": false,

      "malicious_url_categories": [],

      "first_page_url": "https://example.net/one.html",

      "status": "active",

      "url_contains_cdn_cgi_path": false

    }

    // (...)

  ],

  "success": true,

  "errors": [],

  "messages": [],

  "result_info": {

    "page": 1,

    "per_page": 15,

    "count": 15,

    "total_count": 16,

    "total_pages": 2

  }

}


```

For details on the available filtering, paging, and sorting parameters, refer to the [API reference](https://developers.cloudflare.com/api/resources/page%5Fshield/subresources/scripts/methods/list/).

### Get details of a detected connection

This `GET` request obtains the details of a connection detected by Cloudflare's client-side security with connection ID `0a7bb628776f4e50a50d8594c4a01740`.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Page Shield`
* `Domain Page Shield Read`
* `Domain Page Shield`
* `Page Shield Read`
* `Zone Settings Write`
* `Zone Settings Read`

Get a Page Shield connection

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/page_shield/connections/0a7bb628776f4e50a50d8594c4a01740" \

  --request GET \

  --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \

  --header "X-Auth-Key: $CLOUDFLARE_API_KEY"


```

```

{

  "result": {

    "id": "0a7bb628776f4e50a50d8594c4a01740",

    "url": "https://malicious.example.com",

    "added_at": "2022-09-18T10:51:10.09615Z",

    "first_seen_at": "2022-09-18T10:51:08Z",

    "last_seen_at": "2022-09-02T09:57:54Z",

    "host": "example.net",

    "domain_reported_malicious": true,

    "malicious_domain_categories": ["Malware", "Spyware"],

    "url_reported_malicious": false,

    "malicious_url_categories": [],

    "first_page_url": "https://example.net/one.html",

    "status": "active",

    "url_contains_cdn_cgi_path": false

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

### Fetch list of detected cookies

This `GET` request fetches a list of cookies detected by Cloudflare's client-side security, requesting the first page with 15 items per page.

By default, the response will only include cookies with `active` status when you do not specify a `status` filter parameter in the URL query string.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Page Shield`
* `Domain Page Shield Read`
* `Domain Page Shield`
* `Page Shield Read`
* `Zone Settings Write`
* `Zone Settings Read`

List Page Shield Cookies

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/page_shield/cookies?page=1&per_page=15" \

  --request GET \

  --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \

  --header "X-Auth-Key: $CLOUDFLARE_API_KEY"


```

```

{

  "result": [

    {

      "id": "beee03ada7e047e79f076785d8cd8b8e",

      "type": "first_party",

      "name": "PHPSESSID",

      "host": "example.net",

      "domain_attribute": "example.net",

      "expires_attribute": "2024-10-21T12:28:20Z",

      "http_only_attribute": true,

      "max_age_attribute": null,

      "path_attribute": "/store",

      "same_site_attribute": "strict",

      "secure_attribute": true,

      "first_seen_at": "2024-05-06T10:51:08Z",

      "last_seen_at": "2024-05-07T11:56:01Z",

      "first_page_url": "example.net/store/products",

      "page_urls": ["example.net/store/products/1"]

    }

    // (...)

  ],

  "success": true,

  "errors": [],

  "messages": [],

  "result_info": {

    "page": 1,

    "per_page": 15,

    "count": 15,

    "total_count": 16,

    "total_pages": 2

  }

}


```

For details on the available filtering, paging, and sorting parameters, refer to [Make API calls](https://developers.cloudflare.com/fundamentals/api/how-to/make-api-calls/#pagination).

### Get details of a detected cookie

This `GET` request obtains the details of a cookie detected by Cloudflare's client-side security with ID `beee03ada7e047e79f076785d8cd8b8e`.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Page Shield`
* `Domain Page Shield Read`
* `Domain Page Shield`
* `Page Shield Read`
* `Zone Settings Write`
* `Zone Settings Read`

Get a Page Shield cookie

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/page_shield/cookies/beee03ada7e047e79f076785d8cd8b8e" \

  --request GET \

  --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \

  --header "X-Auth-Key: $CLOUDFLARE_API_KEY"


```

```

{

  "result": {

    "id": "beee03ada7e047e79f076785d8cd8b8e",

    "type": "first_party",

    "name": "PHPSESSID",

    "host": "example.net",

    "domain_attribute": "example.net",

    "expires_attribute": "2024-10-21T12:28:20Z",

    "http_only_attribute": true,

    "max_age_attribute": null,

    "path_attribute": "/store",

    "same_site_attribute": "strict",

    "secure_attribute": true,

    "first_seen_at": "2024-05-06T10:51:08Z",

    "last_seen_at": "2024-05-07T11:56:01Z",

    "first_page_url": "example.net/store/products",

    "page_urls": ["example.net/store/products/1"]

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

### Create a content security rule

This `POST` request creates a content security rule (previously called a policy) with _Log_ action, defining the following scripts as allowed based on where they are hosted:

* Scripts hosted in `myapp.example.com` (which does not include scripts in `example.com`).
* Scripts hosted in `cdnjs.cloudflare.com`.
* The Google Analytics script using its full URL.
* All scripts in the same origin (same HTTP or HTTPS scheme and hostname).

All other scripts would trigger a rule violation, but those scripts would not be blocked.

For more information on Content Security Policy (CSP) directives and values, refer to the [MDN documentation ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy).

Note

For a list of CSP directives and keywords supported by content security rules, refer to [Supported CSP directives](https://developers.cloudflare.com/client-side-security/rules/csp-directives/).

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Page Shield`
* `Domain Page Shield`
* `Zone Settings Write`

Create a Page Shield policy

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/page_shield/policies" \

  --request POST \

  --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \

  --header "X-Auth-Key: $CLOUDFLARE_API_KEY" \

  --json '{

    "description": "My first content security rule in log mode",

    "action": "log",

    "expression": "http.host eq \"myapp.example.com\"",

    "enabled": "true",

    "value": "script-src myapp.example.com cdnjs.cloudflare.com https://www.google-analytics.com/analytics.js '\''self'\''"

  }'


```

```

{

  "success": true,

  "errors": [],

  "messages": [],

  "result": {

    "id": "<RULE_ID>",

    "description": "My first content security rule in log mode",

    "action": "log",

    "expression": "http.host eq \"myapp.example.com\"",

    "enabled": "true",

    "value": "script-src myapp.example.com cdnjs.cloudflare.com https://www.google-analytics.com/analytics.js 'self'"

  }

}


```

To create a content security rule with an _Allow_ action instead of _Log_, use `"action": "allow"` in the request body. In the case of such rule, all scripts not allowed by the rule would be blocked.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/reference/api/","name":"Client-side security API"}}]}
```

---

---
title: CSP HTTP header format
description: Format of the Content Security Policy report-only HTTP header added by Cloudflare.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# CSP HTTP header format

The format of the Content Security Policy (CSP) report-only HTTP header added by Cloudflare is the following:

```

content-security-policy-report-only: script-src 'unsafe-inline' 'unsafe-eval'; connect-src 'none'; report-uri https://csp-reporting.cloudflare.com/cdn-cgi/script_monitor/report?<QUERY_STRING>


```

If you [configured the reporting endpoint](https://developers.cloudflare.com/client-side-security/reference/settings/#reporting-endpoint) to use the same hostname, the HTTP header will have the following format:

```

content-security-policy-report-only: script-src 'unsafe-inline' 'unsafe-eval'; connect-src 'none'; report-uri <YOUR_HOSTNAME>/cdn-cgi/script_monitor/report?<QUERY_STRING>


```

Notes

Cloudflare adds the CSP report-only HTTP header used to monitor webpage resources to a sample of sent responses.

Configuring [log rules](https://developers.cloudflare.com/client-side-security/rules/) will add other CSP report-only headers to responses. Cloudflare does not perform any sampling for these report-only headers related to customer-defined content security rules.

## Related resources

* [Mozilla Developer Network's (MDN) documentation on Content-Security-Policy-Report-Only ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy-Report-Only)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/reference/csp-header/","name":"CSP HTTP header format"}}]}
```

---

---
title: Client-side security and PCI DSS compliance
description: Use client-side security to meet PCI DSS v4 requirements 6.4.3 and 11.6.1.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Client-side security and PCI DSS compliance

You can use Cloudflare's client-side security for PCI DSS v4's client-side security requirements (items 6.4.3 and 11.6.1).

Refer to the [PCI DSS v.4.0 Evaluation ↗](https://cfl.re/4dhk8Gx) whitepaper for details on how you can use Cloudflare's client-side security to meet the new v4 requirements.

Note

To help with PCI DSS requirements, you must have Client-Side Security Advanced. Refer to [Availability](https://developers.cloudflare.com/client-side-security/#availability) for details on what is included in each package.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/reference/pci-dss/","name":"Client-side security and PCI DSS compliance"}}]}
```

---

---
title: Roles and permissions
description: User roles and API token permissions required to access and configure client-side security.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Roles and permissions

Cloudflare users with the following [roles](https://developers.cloudflare.com/fundamentals/manage-members/roles/) have access to client-side security in the Cloudflare dashboard:

* Administrator
* Super Administrator - All Privileges
* Page Shield
* Page Shield Read _(read-only access)_
* Domain Page Shield
* Domain Page Shield Read _(read-only access)_

The availability of specific features depends on your client-side security bundle. Refer to [Availability](https://developers.cloudflare.com/client-side-security/#availability) for more information.

## API token permissions

To interact with the [client-side security API](https://developers.cloudflare.com/client-side-security/reference/api/) you need an API token with one of the following [permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/):

* [ Dashboard ](#tab-panel-6847)
* [ API ](#tab-panel-6848)

* Client-side security > Edit
* Client-side security > Read _(read-only access)_

* Page Shield Write
* Page Shield Read _(read-only access)_

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/reference/roles-and-permissions/","name":"Roles and permissions"}}]}
```

---

---
title: Script and connection statuses
description: Status classifications for scripts and connections detected by client-side security.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Script and connection statuses

Cloudflare classifies scripts and connections (also known as resources) according to the following:

* The number of times a script/connection was reported.
* Whether the script/connection is considered malicious or not.

Use client-side security's dashboards to review the scripts loaded in your domain and the connections they make. For more information, refer to [Monitor resources and cookies](https://developers.cloudflare.com/client-side-security/detection/monitor-connections-scripts/).

## Available statuses

* **Infrequent**: There are less than three reports for the script/connection. If there are no reports for a script/connection with _Infrequent_ status for five days, then Cloudflare will delete all the information about the script/connection. Scripts with _Infrequent_ status appear only in the All Reported Scripts dashboard, and connections with _Infrequent_ status appear only in the All Reported Connections dashboard.
* **Active**: There are more than three reports for the script/connection.
* **Inactive**: A previously active script/connection was not reported in the last seven days. If the script/connection is reported again later, its status will change back to _Active_. If the script/connection is not reported for 30 days, Cloudflare will delete all the information about it. Scripts with _Inactive_ status appear only in the All Reported Scripts dashboard, and connections with _Inactive_ status appear only in the All Reported Connections dashboard.

Note

All scripts and connections considered malicious will appear in the Monitors dashboard, regardless of their status.

Malicious script detection is only available to customers with Client-Side Security Advanced.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/reference/script-statuses/","name":"Script and connection statuses"}}]}
```

---

---
title: Configuration settings
description: Configure client-side security monitoring, logging, and connection tracking settings.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configuration settings

## Reporting endpoint

When enabled, client-side security's resource monitoring uses a Content Security Policy (CSP) [report-only HTTP header](https://developers.cloudflare.com/client-side-security/reference/csp-header/) to gather information about all the scripts running on your application.

By default, reports are sent to a Cloudflare-owned endpoint:

```

https://csp-reporting.cloudflare.com/cdn-cgi/script_monitor/report?<QUERY_STRING>


```

Customers with Client-Side Security Advanced can change the reporting endpoint so that the CSP reports are sent to the same hostname:

```

<YOUR-HOSTNAME>/cdn-cgi/script-monitor/report?<QUERY_STRING>


```

### Prerequisites for using the same hostname for CSP reports

Using the same hostname for CSP reporting may interfere with other Cloudflare products. Before selecting this option, ensure that your Cloudflare configuration complies with the following:

* No rate limiting rules match the `cdn-cgi/*` URL path
* No custom rules match the `cdn-cgi/*` URL path

### Configure the reporting endpoint

Note

Only available to customers with Client-Side Security Advanced.

To configure the CSP reporting endpoint:

* [  New dashboard ](#tab-panel-6851)
* [ Old dashboard ](#tab-panel-6852)

1. In the Cloudflare dashboard, go to the Security **Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. (Optional) Filter by **Client-side abuse**.
3. Under **Continuous script monitoring** \> **Configurations**, select the edit icon next to **Reporting endpoint**.
4. Select **Cloudflare-owned endpoint** or **Same hostname**.
5. Select **Save**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Client-side security** \> **Settings**.
3. Under **Reporting endpoint**, select **Cloudflare-owned endpoint** or **Same hostname**.
4. Select **Apply settings**.

## Connection target details

When connection targets are reported to Cloudflare, their URIs can sometimes include sensitive data such as session ID.

By default, client-side security only checks the domain against malicious threat intelligence feeds. You can choose to let Cloudflare use the full URI when analyzing the connections made from your domain's pages. Any sensitive data present in the URI will be logged in clear text, and any user with access to the connection monitor dashboard will be able to view it.

### Configure the connection target details to use

* [  New dashboard ](#tab-panel-6853)
* [ Old dashboard ](#tab-panel-6854)

1. In the Cloudflare dashboard, go to the Security **Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. (Optional) Filter by **Client-side abuse**.
3. Under **Continuous script monitoring** \> **Configurations**, select the edit icon next to **Data processing**.
4. Select **Log host only** to analyze only the hostname or **Log full URI** to use the full URI.
5. Select **Save**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Client-side security** \> **Settings**.
3. Under **Connection target details**, select **Log host only** to analyze only the hostname or **Log full URI** to use the full URI in client-side security.
4. Select **Apply settings**.

## Turn off client-side resource monitoring

When you turn off client-side security's resource monitoring, you lose visibility on the scripts running on your zone, the outbound connections made from pages in your domain, and cookies detected in HTTP traffic.

To turn off client-side resource monitoring:

* [  New dashboard ](#tab-panel-6855)
* [ Old dashboard ](#tab-panel-6856)

1. In the Cloudflare dashboard, go to the Security **Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. (Optional) Filter by **Client-side abuse**.
3. Next to **Continuous script monitoring**, set the toggle to **Off**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Client-side security** \> **Settings**.
3. In **Continuous monitoring and alerting**, select **Disable**.

Turning off client-side security's resource monitoring does not turn off [content security rules](https://developers.cloudflare.com/client-side-security/rules/) (previously known as policies). To turn off content security rules:

* [  New dashboard ](#tab-panel-6849)
* [ Old dashboard ](#tab-panel-6850)

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. (Optional) Filter by **Content security rules**.
3. For each rule, select the three dots next to it > **Disable**.

1. Go to **Security** \> **Client-side security** \> **Rules**.
2. For each rule, set the toggle to **Off**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/client-side-security/","name":"Client-side security"}},{"@type":"ListItem","position":3,"item":{"@id":"/client-side-security/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/client-side-security/reference/settings/","name":"Configuration settings"}}]}
```

---

---
title: Challenges
description: Verify visitors are human using challenge pages, Turnstile, and JavaScript detections.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Challenges

Challenges are security mechanisms used by Cloudflare to verify whether a visitor to your site is a real human and not a bot or automated script.

When a Challenge is issued, Cloudflare asks the browser to perform a series of checks that help confirm the visitor's legitimacy. This process involves evaluating client-side signals (data gathered from the visitor's browser environment) or asking a visitor to take minimal action such as checking a box or selecting a button.

Challenges are designed to protect your application without introducing unnecessary friction. Most visitors will pass Challenges automatically without interaction.

Cloudflare does not use CAPTCHA puzzles or visual tests like selecting objects or typing distorted characters. All challenge types are lightweight, privacy-preserving, and optimized for real-world traffic.

---

## Related products

**[Turnstile](https://developers.cloudflare.com/turnstile/)** 

Use Cloudflare's smart CAPTCHA alternative to run less intrusive Challenges.

**[Bots](https://developers.cloudflare.com/bots/)** 

Cloudflare bot solutions identify and mitigate automated traffic to protect your domain from bad bots.

**[WAF](https://developers.cloudflare.com/waf/)** 

Get automatic protection from vulnerabilities and the flexibility to create custom rules.

**[DDoS Protection](https://developers.cloudflare.com/ddos-protection/)** 

Detect and mitigate Distributed Denial of Service (DDoS) attacks using Cloudflare's Autonomous Edge.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}}]}
```

---

---
title: Troubleshooting
description: Resolve common issues with Cloudflare challenges, including loops and proxied hostnames.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

## Common issues

### Proxied hostnames

If your hostname is proxied through Cloudflare, visitors may experience challenges on your webpages.

Cloudflare issues challenges through the [Challenge Platform](https://developers.cloudflare.com/cloudflare-challenges/), which is the same underlying technology powering [Turnstile](https://developers.cloudflare.com/turnstile/).

In contrast to our Challenge page offerings, Turnstile allows you to run challenges anywhere on your site in a less-intrusive way without requiring the use of Cloudflare's CDN.

### Deprecated browser support

Challenges are not supported by Microsoft Internet Explorer. If you are currently using Internet Explorer, try using another modern web browser (Chrome, Safari, Firefox). If you are already using a modern web browser, make sure it is using the latest version.

### Referer header

Your visitor's HTTP request contains a referer header set to the website that they came from. When they encounter and solve a Challenge Page, the request with the referer is sent to the origin, and the response to the request is served to the user. The JavaScript on the response page may read the value of `document.referer`, but it will not be accurate.

For example, a visitor coming from a given website is challenged by a [WAF rule](https://developers.cloudflare.com/waf/custom-rules/) via an interstitial Challenge Page served by your domain. Once the visitor loads the website's home page, the `document.referer` value is your domain, not the origin website.

This affects tools like Google Analytics, which reads the referer from JavaScript, since it replaces the previous website that visitors came from.

You can add tracking scripts, such as the Google Tag Manager Javascript, within an existing [Challenge Page](https://developers.cloudflare.com/rules/custom-errors/) to capture the correct referer header on the initial request.

Example JavaScript

```

<script>

    (function () {

      const gaIds = {

        "<YOUR_DOMAIN>": "<GA_TRACKING_ID>",

      };


      const gaId = gaIds[window.location.hostname];


      if (gaId) {

        const src = "https://www.googletagmanager.com/gtag/js?id=";


        const gaScript = document.createElement("script");

        gaScript.src = src.concat(gaId);

        document.body.appendChild(gaScript);


        window.dataLayer = window.dataLayer || [];

        function gtag() {

          dataLayer.push(arguments);

        }

        gtag("js", new Date());

        gtag("config", gaId);

      } else {

        console.warn(

          "Google Analytics ID not found for host:",

          window.location.hostname,

        );

      }

    })();

  </script>

</body>


```

### Cross-origin resource sharing (CORS) preflight requests

Cross-origin resource sharing (CORS) preflight requests, or `OPTIONS`, exclude user credentials that include cookies. As a result, the `cf_clearance` cookie will not be sent with the request, causing it to fail to bypass a Challenge Page (Non-interactive, Managed, or Interactive Challenge).

### Challenges on Cloudflare-protected sites

Cloudflare issues challenges to website visitors to protect against malicious activity, such as bot attacks and DDoS attempts. If a legitimate human visitor is unexpectedly challenged, the reason typically stems from a security feature flagging their request.

| Source                                      | Description                                                                 |
| ------------------------------------------- | --------------------------------------------------------------------------- |
| High threat score                           | IP addresses with a high-risk score trigger Challenges.                     |
| IP reputation                               | If your IP has a history of suspicious activity, it may be flagged.         |
| Bot detection                               | Automated traffic resembling bots is filtered by Cloudflare.                |
| Web Application Firewall (WAF) custom rules | Site owners may set rules targeting specific regions or user agents.        |
| Browser Integrity Check                     | Cloudflare verifies that browsers meet certain standards.                   |
| Challenge Passage                           | Technologies like Privacy Pass reduce the frequency of repeated Challenges. |

To avoid repeated challenges, visitors can take the following steps to ensure their environment does not trigger security checks:

* Ensure your web browser is updated to the latest stable version for full compatibility with modern challenge technologies.
* Temporarily disable browser extensions, such as ad blockers or privacy tools, that may block standard browser headers or the necessary challenge scripts.
* If your IP address has a poor reputation (often seen with shared VPNs or corporate proxies), try switching to a different, trusted network connection.

### Allowlist traffic from mitigation actions

If you need to prevent a **Block** or **Challenge** action from being applied to specific requests, such as known search engine crawlers, monitoring services, or internal APIs, you must configure an exclusion using [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/).

Cloudflare supports two primary methods for creating these exclusions:

#### 1\. Use a Skip rule (recommended)

The most robust method for creating an exception is to create a custom rule with the **Skip** action. This allows matching requests to bypass certain security features, including Bot Management and other WAF rules.

Note

Due to the evaluation order, **Skip** rules must be positioned before the **Block** or **Challenge** rule they are designed to bypass.

Example

Block Amazon Web Services (AWS) and Google Cloud Platform (GCP) because of large volumes of undesired traffic, but allow Googlebot and other known bots that Cloudflare validates.

* Basic rule, no exclusion:  
   * **Expression**: `(ip.src.asnum in {16509 15169} and not cf.client.bot)`  
   * **Action**: Block (or a challenge action)
* Rule that excludes IP addresses from being blocked or challenged:  
   * **Expression**: `(ip.src.asnum in {16509 15169} and not cf.client.bot) and not (ip.src in {192.0.2.1 198.51.100.42 203.0.113.0/24})`  
   * **Action**: Block (or a challenge action)
* Two rules to skip remaining custom rules for specific IPs and block the rest.  
   1. Rule 1:  
         * Expression: `ip.src in {192.0.2.1 198.51.100.42 203.0.113.0/24}`  
         * Action: Skip > All remaining custom rules  
   2. Rule 2:  
         * Expression: `(ip.src.asnum in {16509 15169} and not cf.client.bot)`  
         * Action: Block (or a challenge action)

#### 2\. Modify the Rule Expression

You can refine the expression of a **Block** or **Challenge** rule to directly exclude known good traffic by using the logical not operator with an exclusion list, such as an IP list, country code, or ASN.

This approach is useful for simple exclusions but can make complex rules more difficult to maintain than separate **Skip** rules.

Example

Exclude multiple IP addresses from a **Block** or **Challenge** rule that assesses attack score.

* Basic rule, no exclusion:  
   * **Expression**: `(http.host eq "example.com" and cf.waf.score lt 20)`  
   * **Action**: Block (or a challenge action)
* Rule that excludes IP addresses from being blocked/challenged:  
   * **Expression**: `(http.host eq "example.com" and cf.waf.score lt 20) and not (ip.src in {192.0.2.1 198.51.100.42 203.0.113.0/24})`  
   * **Action**: Block (or a challenge action)
* Two rules to skip remaining custom rules for specific IPs and block the rest.  
   1. Rule 1:  
         * Expression: `ip.src in {192.0.2.1 198.51.100.42 203.0.113.0/24}`  
         * Action: Skip > All remaining custom rules  
   2. Rule 2:  
         * Expression: `(http.host eq "example.com" and cf.waf.score lt 20)`  
         * Action: Block (or a challenge action)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: Challenge solve issues
description: Fix challenge loops, unsupported browser errors, and other solve failures.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Challenge solve issues

## Challenge loops

You may encounter a challenge loop where the challenge keeps reappearing without being solved. This is in very specific cases where we detect strong bot signals. If you are a legitimate human, you can follow the troubleshooting guide below to resolve the issue or submit a feedback report. Challenge loops can happen for several reasons:

* **Network issues**: Poor or unstable network connections can prevent the challenge from being completed.
* **Browser configuration**: Some browser settings or extensions may block the scripts needed to execute the challenge.
* **Unsupported browsers**: Using a browser that is not supported by Turnstile.
* **JavaScript disabled**: Turnstile relies on JavaScript to function properly.
* **Detection errors**: If Turnstile suspects bot-like behavior, you may encounter repeated challenges for verification.

Most challenges are quick to complete and typically take only a few seconds. If it takes longer, ensure your network is stable and follow the [troubleshooting steps](#troubleshooting).

Note

If the issue persists, try switching to a different network or device to rule out any issues with your browser environment.

Ensure your browser is updated to the latest version to maintain compatibility.

## Troubleshooting

Follow the steps below to ensure that your environment is properly configured.

1. Verify your browser compatibility.  
   * Turnstile supports all major browsers, except Internet Explorer.  
   * Ensure your browser is up to date. For more information, refer to our [Supported browsers](https://developers.cloudflare.com/cloudflare-challenges/reference/supported-browsers/).  
   * Run a test on the [compatibility checking tool ↗](https://browser-compat.turnstile.workers.dev/).
2. Disable your browser extensions.  
   * Some browser extensions, such as ad blockers, may block the scripts Turnstile needs to operate.  
   * Temporarily disable all extensions and reload the page.
3. Enable JavaScript.  
   * Turnstile requires JavaScript to run. Ensure it is enabled in your browser settings. Refer to your browser's documentation for instructions on enabling JavaScript.
4. Try Incognito or Private mode.  
   * Use your browser's incognito or private mode to rule out issues caused by extensions or cached data.
5. Test another browser or device.  
   * Switch to a different browser or device to see if the issue is specific to your current setup.
6. Avoid VPNs or proxies.  
   * Some virtual private networks (VPN) or proxies may interfere with Turnstile. Disable them temporarily to test.
7. Switch to a different network.  
   * Your current network may have restrictions causing Turnstile challenges to fail. Try switching to another network, such as a mobile hotspot.

If none of the above resolves your issue, contact the website administrator with the [error code](https://developers.cloudflare.com/turnstile/troubleshooting/client-side-errors/error-codes/) and Ray ID or submit a [feedback report](https://developers.cloudflare.com/turnstile/troubleshooting/feedback-reports/) through the Turnstile widget by selecting **Submit Feedback**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/troubleshooting/challenge-solve-issues/","name":"Challenge solve issues"}}]}
```

---

---
title: Interstitial Challenge Pages
description: Full-page challenge screens that verify visitors before they reach your website.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Interstitial Challenge Pages

An interstitial Challenge Page (a full-page screen that appears before the visitor reaches the destination URL) acts as a gate between the visitor and your website or application while Cloudflare verifies the authenticity of the visitor.

The Challenge Page intercepts the visitor from getting to the destination URL by holding the request and evaluating the browser environment for automated signals, and serving a challenge. The visitor cannot reach their destination without passing the challenge. Based on the signals indicated by their browser environment, the visitor may be asked to perform an interaction such as checking a box or selecting a button for further probing.

You can implement a Challenge Page to your website or application by creating a [WAF custom rule](https://developers.cloudflare.com/waf/custom-rules/).

Challenges are triggered by a rule in the [Web Application Firewall (WAF)](https://developers.cloudflare.com/waf/), [Bot Management](https://developers.cloudflare.com/bots/), or [Rate limiting](https://developers.cloudflare.com/waf/rate-limiting-rules/).

The level of interactivity and visibility of the Challenge Page depends on the Action that you select when creating the WAF rule for your website or application.

## Actions

The following challenge types are the available actions when you create a WAF rule for a Challenge Page.

### Non-Interactive Challenges

With a Non-Interactive Challenge, Cloudflare makes the determination on whether or not the visitor is automated based on the limited information attained from their browser signals via an injected JavaScript. Then, it presents a Challenge Page that requires no interaction from a visitor except the JavaScript processed by their browser.

The visitor must wait until their browser finishes processing the JavaScript, which typically takes less than five seconds.

If the visitor passes the challenge, the original request continues to the destination URL. If the challenge fails or cannot be completed, the visitor is presented with another interstitial Challenge Page.

### Managed Challenges

Managed Challenges are where Cloudflare dynamically chooses the appropriate type of challenge served to the visitor based on the characteristics of a request from the signals indicated by their browser. This helps avoid [CAPTCHAs ↗](https://www.cloudflare.com/learning/bots/how-captchas-work/), which also reduces the lifetimes of human time spent solving CAPTCHAs across the Internet.

Most human visitors are automatically verified and the Challenge Page will display **Successful**. However, if Cloudflare detects non-human attributes from the visitor's browser, they may be required to interact with the challenge to solve it.

Cloudflare recommends Managed Challenges for most WAF rules. Unless there are specific compatibility issues, do not use other challenge types.

Warning

Using Cloudflare Challenges along with Rules features may cause challenge loops. Refer to [Rules troubleshooting](https://developers.cloudflare.com/rules/reference/troubleshooting/) for more information.

### Interactive Challenges

Interactive Challenge Pages require a visitor to interact with the challenge to pass.

Cloudflare always recommends using a Managed Challenge. For more information, refer to the [Cloudflare blog post ↗](https://blog.cloudflare.com/end-cloudflare-captcha/).

## Compatibility limitations

Challenge Pages interrupt the request flow by returning a full HTML page for the user's browser to render and solve. This mechanism fails when the browser expects a non-HTML response, such as an AJAX or XHR (fetch) request.

To ensure your API calls are protected without breaking single-page applications (SPAs) or API integrations, Cloudflare recommends using Turnstile Pre-clearance.

By enabling Pre-clearance, the Turnstile widget issues a persistent clearance cookie (`cf_clearance`) upon successful human verification on an initial HTML page. This cookie pre-clears the visitor to interact with sensitive API endpoints secured by WAF rules, allowing you to deploy granular security without forcing a disruptive Challenge Page response.

For implementation details, refer to the [guidance on Pre-clearance for Turnstile](https://developers.cloudflare.com/cloudflare-challenges/concepts/clearance/#pre-clearance-support-in-turnstile).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/challenge-types/","name":"Available Challenges"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/challenge-types/challenge-pages/","name":"Interstitial Challenge Pages"}}]}
```

---

---
title: Additional configuration
description: Customize challenge pages with multi-language support, branding, and text options.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Additional configuration

## Multi-language support

Refer to [supported languages](https://developers.cloudflare.com/cloudflare-challenges/reference/supported-languages/) for more information.

---

## Favicon customization

Cloudflare Challenges take the favicon of your website using `GET /favicon.ico` and displays it on the Challenge Page.

You can customize your favicon by using the HTML snippet below.

HTML element

```

<link rel="shortcut icon" href="<FAVICON_LINK>" />


```

---

## Custom Content Security Policy (CSP) and error pages

A Content Security Policy (CSP) controls which scripts and resources a browser is allowed to load on a page. Challenge pages depend on specific Cloudflare scripts, so custom CSP configurations can prevent challenges from working.

You cannot set your own CSP or Referer-Policy on challenge pages using `<meta>` tags or [Transform Rules](https://developers.cloudflare.com/rules/transform/). Origin response headers can still be modified in a challenge page context, but doing so may cause the challenge to break.

If you have a [Transform Rule](https://developers.cloudflare.com/rules/transform/) that modifies HTTP response headers across your website (for example, adding custom CSP headers), the rule will interfere with challenge pages and cause them to fail.

To prevent this, modify your Transform Rule expression to exclude challenge page responses. Add the following condition to the beginning of your expression:

```

not cf.response.error_type in {"managed_challenge" "iuam" "legacy_challenge" "country_challenge"}


```

This expression skips your header modifications when Cloudflare serves a challenge page, so the challenge scripts load correctly.

---

## Custom Challenge Pages

Before defining a custom Challenge Page in your Cloudflare account, you will need to design and code that page. It can be hosted on your own web server or using a Cloudflare product like [Snippets](https://developers.cloudflare.com/rules/snippets/).

Refer to [Design your custom error page](https://developers.cloudflare.com/rules/custom-errors/edit-error-pages/#1-design-your-custom-error-page) for more information.

### How it works

When you configure a custom challenge page, Cloudflare fetches your uploaded HTML template and replaces the `::CF_WIDGET_BOX::` placeholder with the challenge script.

### Placeholder tokens

The custom error token provides diagnostic information or specific functionality that appears on the error page. Refer to [Error tokens](https://developers.cloudflare.com/rules/custom-errors/reference/error-tokens/) for more details.

* `::CF_WIDGET_BOX::`
* `::CAPTCHA_BOX::`
* `::IM_UNDER_ATTACK_BOX::`
* `::CLIENT_IP::`
* `::RAY_ID::`
* `::GEO::`

Note

`::CF_WIDGET_BOX::` is always replaced regardless of challenge type — use this for new templates.

### Requirements

1. `::CF_WIDGET_BOX::` must appear exactly once in the body. This is where the challenge script is injected.
2. `<head>` tag must be present.
3. Cloudflare will set `cTplC: 1` in the browser's `window._cf_chl_opt` when a custom template is in use. Do not add your own `window._cf_chl_opt`. Any existing definition will cause conflicts.
4. Do not block `/cdn-cgi/challenge-platform/` paths via Content Security Policy (CSP). Challenges will not work correctly with this kind of block in place.
5. The page is served for all three challenge types (managed, interactive, non-interactive) if you use `::CF_WIDGET_BOX::`.

### Templates

* [ Minimal template ](#tab-panel-6861)
* [ Full template ](#tab-panel-6862)

Example

```

<!DOCTYPE html>

<html lang="en-US">

<head>

  <title>Example Title</title>

  <meta charset="UTF-8">

  <meta name="viewport" content="width=device-width,initial-scale=1">

</head>

<body>

  ::CF_WIDGET_BOX::

</body>

</html>


```

Example

```

<!DOCTYPE html>

<html lang="en-US">

<head>

  <title>Security Check — example.com</title>

  <meta charset="UTF-8">

  <meta http-equiv="X-UA-Compatible" content="IE=Edge">

  <meta name="robots" content="noindex,nofollow">

  <meta name="viewport" content="width=device-width,initial-scale=1">

  <style>

    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

    body {

      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

      background: #f8f9fa;

      color: #1a1a2e;

      min-height: 100vh;

      display: flex;

      flex-direction: column;

      align-items: center;

      justify-content: center;

      padding: 1rem;

    }

    .card {

      background: #ffffff;

      border-radius: 12px;

      box-shadow: 0 4px 24px rgba(0,0,0,0.08);

      padding: 2.5rem 3rem;

      max-width: 520px;

      width: 100%;

      text-align: center;

    }

    .logo {

      width: 64px;

      height: 64px;

      margin: 0 auto 1.5rem;

    }

    h1 {

      font-size: 1.4rem;

      font-weight: 600;

      margin-bottom: 0.5rem;

    }

    .subtitle {

      font-size: 0.95rem;

      color: #666;

      margin-bottom: 2rem;

      line-height: 1.5;

    }

    /* The challenge widget will be injected here — give it space */

    .challenge-widget {

      margin: 1.5rem 0;

      min-height: 65px;        /* Turnstile widget is ~65px tall */

      display: flex;

      align-items: center;

      justify-content: center;

    }

    .meta {

      margin-top: 2rem;

      font-size: 0.75rem;

      color: #aaa;

      line-height: 1.6;

    }

    noscript .noscript-warning {

      background: #fff3cd;

      border: 1px solid #ffc107;

      border-radius: 8px;

      padding: 1rem;

      font-size: 0.9rem;

      color: #856404;

      margin-bottom: 1rem;

    }

  </style>

</head>

<body>

  <div class="card">

    <!-- Your logo / branding -->

    <svg class="logo" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">

      <circle cx="32" cy="32" r="32" fill="#E8F4FD"/>

      <path d="M32 16a16 16 0 1 1 0 32A16 16 0 0 1 32 16zm0 4a12 12 0 1 0 0 24A12 12 0 0 0 32 20z"

            fill="#0051C3"/>

      <circle cx="32" cy="32" r="4" fill="#0051C3"/>

    </svg>

    <h1>Verifying you are human</h1>

    <p class="subtitle">

      This security check helps us protect example.com from automated traffic.

      It will only take a moment.

    </p>

    <noscript>

      <div class="noscript-warning">

        Please enable JavaScript and cookies to continue.

      </div>

    </noscript>

    <!--

      REQUIRED: One of the following placeholders must appear exactly once.

      Cloudflare will replace it with the challenge bootstrap <script>.

      Use ::CF_WIDGET_BOX:: for all challenge types (recommended).

      Older alternatives:

        ::CAPTCHA_BOX::          — managed / interactive challenges

        ::IM_UNDER_ATTACK_BOX:: — non-interactive / JS challenge

    -->

    <div class="challenge-widget">

      ::CF_WIDGET_BOX::

    </div>

    <div class="meta">

      Performance & security by your company<br>

      Ray ID: <code>::RAY_ID::</code> •

      Your IP: <code>::CLIENT_IP::</code> •

      Country: <code>::GEO::</code>

    </div>

  </div>

</body>

</html>


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/challenge-types/","name":"Available Challenges"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/challenge-types/challenge-pages/","name":"Interstitial Challenge Pages"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-challenges/challenge-types/challenge-pages/additional-configuration/","name":"Additional configuration"}}]}
```

---

---
title: Challenge Passage
description: Set a time period during which visitors do not have to solve repeat challenges.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Challenge Passage

When a visitor solves a [Cloudflare Challenge](https://developers.cloudflare.com/cloudflare-challenges/) \- as part of a [WAF custom rule](https://developers.cloudflare.com/waf/custom-rules/) or [IP Access rule](https://developers.cloudflare.com/waf/tools/ip-access-rules/) \- you can set the **Challenge Passage** to prevent them from having to solve future Challenges for a specified period of time.

### How it works

When a visitor successfully solves a challenge, Cloudflare sets a [cf\_clearance cookie](https://developers.cloudflare.com/fundamentals/reference/policies-compliances/cloudflare-cookies/#additional-cookies-used-by-the-challenge-platform) in their browser. This cookie specifies the duration your website is accessible to that visitor.

When that visitor tries to access other parts of your website, Cloudflare evaluates the cookie before presenting another challenge. If the cookie is still valid, no challenges will be shown.

When Cloudflare evaluates a `cf_clearance` cookie, a few extra minutes are included to account for clock skew. For XmlHTTP requests, an extra hour is added to the validation time to prevent breaking XmlHTTP requests for pages that set short lifetimes.

### Customize the Challenge Passage

By default, the `cf_clearance` cookie has a lifetime of 30 minutes. Cloudflare recommends a setting between 15 and 45 minutes.

To update the Challenge Passage (and the value of the `cf_clearance` cookie):

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Go to **Challenge passage**.
3. Select the edit icon to set a timeout duration.

### Limitations

The Challenge Passage does not apply to rate limiting rules.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/challenge-types/","name":"Available Challenges"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/challenge-types/challenge-pages/","name":"Interstitial Challenge Pages"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-challenges/challenge-types/challenge-pages/challenge-passage/","name":"Challenge Passage"}}]}
```

---

---
title: Implement a Challenge Page via WAF custom rules
description: Create WAF custom rules that issue challenge pages based on bot scores or rate limits.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Implement a Challenge Page via WAF custom rules

You can implement a Challenge Page to your website or application by creating a [WAF custom rule](https://developers.cloudflare.com/waf/custom-rules/).

Challenges are triggered by a rule in the [Web Application Firewall (WAF)](https://developers.cloudflare.com/waf/), [Bot Management](https://developers.cloudflare.com/bots/), or [Rate limiting](https://developers.cloudflare.com/waf/rate-limiting-rules/).

* **Bot Management**: Challenge visitors that appear automated based on their [bot score](https://developers.cloudflare.com/bots/concepts/bot-score/) or a specific [detection ID](https://developers.cloudflare.com/bots/additional-configurations/detection-ids/).
* **Rate limiting**: Challenge visitors who exceed your configured [rate limits](https://developers.cloudflare.com/waf/rate-limiting-rules/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/challenge-types/","name":"Available Challenges"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/challenge-types/challenge-pages/","name":"Interstitial Challenge Pages"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-challenges/challenge-types/challenge-pages/create-custom-rule/","name":"Implement a Challenge Page via WAF custom rules"}}]}
```

---

---
title: Detect a Challenge Page response
description: Use the cf-mitigated header to identify challenge page responses in fetch and XHR requests.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Detect a Challenge Page response

When a request encounters a Cloudflare Challenge Page instead of the originally anticipated response, the Challenge Page response (regardless of the Challenge Page type) will have the `cf-mitigated` header present and set to `challenge`. This header can be leveraged to detect if a response was challenged when making fetch/XHR requests. This header provides a reliable way to identify whether a response is a Challenge or not, enabling a web application to take appropriate action based on the result. For example, a front-end application encountering a response from the backend may check the presence of this header value to handle cases where Challenge Pages encountered unexpectedly.

Note

Regardless of the requested resource-type, the content-type of a challenge will be `text/html`.

For the `cf-mitigated` header, `challenge` is the only valid value. The header is set for all Challenge Page types.

To illustrate, here is a JavaScript code snippet that demonstrates how to use the `cf-mitigated` header to detect whether a response was challenged:

JavaScript

```

fetch("/my-api-endpoint").then((response) => {

  if (response.headers.get("cf-mitigated") === "challenge") {

    // Handle challenged response

  } else {

    // Process response as usual

  }

});


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/challenge-types/","name":"Available Challenges"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/challenge-types/challenge-pages/","name":"Interstitial Challenge Pages"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-challenges/challenge-types/challenge-pages/detect-response/","name":"Detect a Challenge Page response"}}]}
```

---

---
title: Resolve a Challenge
description: Steps visitors and site owners can take when encountering a Cloudflare challenge page.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Resolve a Challenge

If a visitor encounters a Challenge, Cloudflare employees cannot remove that Challenge. Only the website owner can configure their Cloudflare settings to stop the Challenge being presented.

When observing a Cloudflare Challenge page, a visitor could:

* Successfully pass the Challenge to visit the website.
* Request the website owner to allow their IP address.
* Scan their computer for malicious programs (it may be infected).
* Check their antivirus or firewall service to make sure it is not blocking access to the Challenge resources (for example, images).

Note

Visitors must enable JavaScript and cookies on their browser to be able to pass any type of Challenge.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/challenge-types/","name":"Available Challenges"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/challenge-types/challenge-pages/","name":"Interstitial Challenge Pages"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-challenges/challenge-types/challenge-pages/resolve-challenge/","name":"Resolve a Challenge"}}]}
```

---

---
title: JavaScript Detections
description: Client-side JavaScript challenges that run on every request to identify automated traffic.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# JavaScript Detections

JavaScript Detections is a type of challenge separate from Cloudflare’s Challenge Pages or Turnstile. JavaScript Detections helps Cloudflare's [bot solutions](https://developers.cloudflare.com/bots/) identify automated requests.

While Challenge Pages and Turnstile rely on client-side signals to determine the authenticity of a request, Bot Management’s JavaScript Detections relies on client-side signals and runs on every single request made to your website.

## Process

JavaScript Detections is implemented on your website via a lightweight, invisible JavaScript code snippet that follows Cloudflare's [privacy standards ↗](https://www.cloudflare.com/privacypolicy/).

JavaScript is injected only in response to requests for HTML pages or page views, excluding AJAX calls. API and mobile application traffic is unaffected.

JavaScript Detections has a lifespan of 15 minutes. However, the code is injected again before the session expires. After page load, the script is deferred and utilizes a separate thread (where available) to ensure that performance impact is minimal. The snippets of JavaScript will contain a source pointing to the Challenge Platform, with paths that start with `/cdn-cgi/challenge-platform/…`

Once JavaScript Detections is injected on the HTML page, the visitor's browser will run the JavaScript code snippet and a `cf_clearance` cookie is issued to the visitor. The information in JavaScript Detections is stored in the `cf_clearance` cookie and is used to populate `js_detection.passed`.

* If the visitor is verified and a `cf_clearance` cookie is issued, it will contain the outcome: `cf.bot_management.js_detection.passed` \= `true`
* If the verification fails, the cookie will contain the outcome: `cf.bot_management.js_detection.passed` \= `false`

Note

The `cf_clearance` cookie cannot exceed the maximum size of 4096 bytes.

Warning

Enforcement against bots does **not** occur even if the cookie is flagged false.

You must enable JavaScript Detections and then create a custom WAF rule using the `cf.bot_management.js_detection.passed` field to block or challenge a failed request.

When the visitor encounters a WAF custom rule on your website, the rule will check the outcome of the `cf_clearance` cookie. The outcome of the `cf_clearance` cookie determines whether the request passes, or is blocked or challenged.

Refer to the steps below to enable and enforce JavaScript Detections.

## 1\. Enable JavaScript Detections

For Bot Fight Mode customers, [JavaScript Detections](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/javascript-detections/) is automatically enabled and cannot be disabled.

For Super Bot Fight Mode and Bot Management for Enterprise customers, [JavaScript Detections](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/javascript-detections/) is optional.

* [  New dashboard ](#tab-panel-6865)
* [ Old dashboard ](#tab-panel-6866)

1. In the Cloudflare dashboard, go to the **Security Settings** page.  
[ Go to **Settings** ](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Under your bot traffic plan configurations, select the edit icon for **JS detections** and turn **JavaScript Detections** on.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Bots**.
3. Select **Configure Bot Management**.
4. For **JavaScript Detections**, switch the toggle to **On**.

For more details on how to set up bot protection, refer to the [Bots documentation](https://developers.cloudflare.com/bots/get-started/).

## 2\. Enforce execution of JavaScript Detections

Once you enable JavaScript detections, you must use the `cf.bot_management.js_detection.passed` field to create [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/) (or the `request.cf.botManagement.jsDetection.passed` variable in [Workers](https://developers.cloudflare.com/workers/)).

When adding this field to WAF custom rules, it is used on endpoints expecting browser traffic (avoiding native mobile applications or websocket endpoints), after a user's first request to your application (Cloudflare needs at least one HTML request before injecting JavaScript detection), and with the Managed Challenge action, because there are legitimate reasons a user might not have passed a JavaScript Detection challenge (network issues, ad blockers, disabled JavaScript in browser, native mobile applications).

### Prerequisites

* You must have an [Enterprise Bot Management](https://developers.cloudflare.com/bots/plans/bm-subscription/) subscription.
* You must have JavaScript Detections enabled on your zone.
* You must have [updated your Content Security Policy headers](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/javascript-detections/#if-you-have-a-content-security-policy-csp) for JavaScript detections.
* You must not run this field on websocket endpoints.
* You must use the field in a custom rules expression that expects only browser traffic.
* The action should always be a managed challenge in case a legitimate user has not received the challenge for network or browser reasons.
* The path specified in the rule builder should never be the first HTML page a user visits when browsing your site.

The `cf.bot_management.js_detection.passed` field should never be used in a WAF custom rule that matches a visitor's first request to a site. It is necessary to have at least one HTML request before Cloudflare can inject JavaScript detection.

* [ WAF rule example ](#tab-panel-6863)
* [ Workers example ](#tab-panel-6864)

```

(http.request.uri.path eq "/api/v4/user/create" and http.request.method eq "POST" and not cf.bot_management.verified_bot)

and (cf.bot_management.score lt 30 or !cf.bot_management.js_detection.passed)


```

JavaScript

```

"botManagement": {

"jsDetection": {

    "passed": false

}

}


```

Refer to the [WAF documentation](https://developers.cloudflare.com/waf/custom-rules/create-dashboard/) for more information on creating a custom rule.

## API

If you enable JavaScript Detections via the dashboard, Cloudflare will insert a script tag in all HTML pages served on your website. If you would prefer to limit where JavaScript Detections is served, you can do so with the JavaScript Detections API script.

The JavaScript Detections API allows you more granular control over when and where JavaScript Detections is injected on your website, as well as an option for callback handling (for logging or other additional actions).

You can explicitly add a script reference to `/cdn-cgi/challenge-platform/scripts/jsd/api.js` and your own code calling `window.cloudflare.jsd.executeOnce` on specific HTML pages of your website.

Warning

It is not recommended to combine both approaches (zone-wide toggle and the manual injection). If you want to selectively deploy JavaScript Detections only on certain pages, disable JavaScript Detections via the Cloudflare dashboard and use the JavaScript Detections API exclusively.

The following script must be added to every page that you wish to have JavaScript Detections enabled:

```

<script>


function jsdOnload(){

  window.cloudflare.jsd.executeOnce(

    {

      callback: function(result){

        console.log('jsd outcome', result);

      }

    }

  );

}

</script>

<script src="/cdn-cgi/challenge-platform/scripts/jsd/api.js?onload=jsdOnload" async>


```

Note

`result` \= `success` or `error` only refers to the execution of JavaScript Detections. It does not indicate whether a visitor is a human or a bot.

## Considerations

JavaScript Detections does not guarantee a specific bot score.

* If the JavaScript Detections injection or execution fails and `cf.bot_management.js_detection.passed` \= `false`, a separate Bot Management heuristic can still yield a `1` or higher bot score, independent of JavaScript Detections.
* If the JavaScript Detections passes, the final bot score may still be `1` due to other detection heuristics (for example, known malicious IP, signature detection, and more), resulting in `js_detection.passed` \= `true`, but `score` \= `1`.

## Limitations

### If you enabled Bot Management before June 2020

Customers who enabled Enterprise Bot Management before June 2020 do not have JavaScript Detections enabled by default (unless specifically requested). These customers can still enable the feature in the Cloudflare dashboard.

### If it is the first request to your website

The first request from a new client to your website or application will generally not have JavaScript Detections data (`cf.bot_management.js_detection.passed` \= `false`). This is because Cloudflare needs at least one HTML request before injecting JavaScript Detection and issuing the `cf_clearance` cookie.

Subsequent requests can include a `cf_clearance` cookie if JavaScript ran successfully.

### If you have a Content Security Policy (CSP)

If you have a Content Security Policy (CSP), you need to take additional steps to implement JavaScript Detections:

* Ensure that anything under `/cdn-cgi/challenge-platform/` is allowed. Your CSP should allow scripts served from your origin domain (`script-src self`).
* For `nonce` script tags:  
   * If your CSP uses a `nonce` for script tags, Cloudflare will add these nonces to the scripts it injects by parsing your CSP response header.  
   * If your CSP does not use `nonce` for script tags and **JavaScript Detections** is enabled, you may see a console error such as `Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-b123b8a70+4jEj+d6gWI9U6IilUJIrlnRJbRR/uQl2Jc='), or a nonce ('nonce-...') is required to enable inline execution.` We highly discourage the use of `unsafe-inline` and instead recommend the use CSP `nonces` in script tags which we parse and support in our CDN.

Warning

JavaScript Detections is not supported with `nonce` set via `<meta>` tags.

### If you have ETags

Enabling JavaScript Detections (JSD) will strip [ETags](https://developers.cloudflare.com/cache/reference/etag-headers/) from HTML responses where JSD is injected.

### If your origin sends a `no-transform` header

If the origin response includes a `Cache-Control: no-transform` directive, Cloudflare does not inject the JavaScript Detections script. The `cf.bot_management.js_detection.passed` field will show as `missing` for these requests.

To use JavaScript Detections, remove the `no-transform` directive from `Cache-Control` response headers on pages where you want JavaScript Detections to run. For more information, refer to [Cache-Control directives](https://developers.cloudflare.com/cache/concepts/cache-control/#interaction-with-other-cloudflare-features).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/challenge-types/","name":"Available Challenges"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/challenge-types/javascript-detections/","name":"JavaScript Detections"}}]}
```

---

---
title: Turnstile
description: Embed a CAPTCHA-alternative widget that verifies visitors without interrupting their experience.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Turnstile

[Turnstile](https://developers.cloudflare.com/turnstile/) is Cloudflare's CAPTCHA-alternative solution. You can embed Turnstile as a widget on your website or application, where it runs a client-side challenge directly in the background of the visitor's browser.

Turnstile differs from Challenges Pages in that the challenge does not pause the request or interrupt the user's experience. Since the widget is embedded onto the webpage and only runs on a specific part of the HTML, the visitor will have already arrived at the destination URL and is viewing the page when they encounter a Turnstile widget. Instead of blocking the visitor from accessing the entire website, the Turnstile widget prevents the visitor from certain actions such as completing login or sign up forms, and more, until the widget is solved.

In most cases, nothing further is required from the visitor. However, if necessary, Turnstile may display a simple checkbox that the visitor must click to proceed.

After the challenge passes, Turnstile issues a clearance token to the visitor that must be validated via the [Siteverify API](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/) before completing a sensitive action like login, sign up, or other form submissions.

Warning

It is critical to enforce Turnstile tokens with the Siteverify API. The Turnstile token could be invalid, expired, or already redeemed. Not verifying the token will leave major vulnerabilities in your implementation.

You **must** call Siteverify to complete your Turnstile configuration. Otherwise, it is incomplete and will result in zeroes for token validation when viewing your metrics in [Turnstile Analytics](https://developers.cloudflare.com/turnstile/turnstile-analytics/).

## Widget types

While there are three types of widgets that you can choose to implement on your website or application, the challenge logic behind them remains the same.

* **Managed (recommended)**: Functions similar to a Managed Challenge Page. It selects a challenge based on the signals gathered from the visitor's browser and presents an interaction only if it detects potentially automated traffic.
* **Non-Interactive**: The widget is displayed, but the visitor does not need to interact with it to verify their identity.
* **Invisible**: The widget is completely invisible to the visitor, but the challenge still runs in the background.  
Link to Cloudflare's Turnstile Privacy Policy  
As a condition of enabling invisible mode, you must reference Cloudflare's [Turnstile Privacy Addendum ↗](https://www.cloudflare.com/turnstile-privacy-policy/) in your own privacy policy.

## Implementation

When you create a widget for your website or application via the Cloudflare dashboard, you will receive a sitekey.

The sitekey is used with [client-side rendering](https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/#implicitly-render-the-turnstile-widget) by adding it to the `<div>` container placeholder. You will then place that `<div>` code snippet where you want to add the widget to your site page or form.

## Get started

Refer to the [Turnstile documentation](https://developers.cloudflare.com/turnstile/get-started/) for guidance on implementing a widget to your website or application.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/challenge-types/","name":"Available Challenges"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/challenge-types/turnstile/","name":"Turnstile"}}]}
```

---

---
title: Clearance
description: How cf_clearance cookies prove a visitor passed a Cloudflare challenge.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Clearance

## `cf_clearance` cookies

A `cf_clearance` cookie proves to Cloudflare that the visitor is a verified human and has passed the challenge presented to them.

The `cf_clearance` cookie is securely tied to the specific visitor and device it was issued to. This binding is a security feature designed to prevent the cookie from being easily transferred and re-used on other machines.

As an additional layer of security, Cloudflare recommends that customers [add a rate limiting rule](https://developers.cloudflare.com/waf/rate-limiting-rules/) based on the `cf_clearance` cookie value. This ensures that a single, valid cookie cannot be abused by a single machine to send an excessive volume of requests.

Each challenge type sets a clearance level. A higher-level cookie bypasses all challenge types at or below that level. A lower-level cookie only bypasses challenges at the same level.

| Clearance level       | Bypasses                                             |
| --------------------- | ---------------------------------------------------- |
| Interactive (high)    | Interactive, Managed, and Non-Interactive Challenges |
| Managed (medium)      | Managed and Non-Interactive Challenges               |
| Non-Interactive (low) | Non-Interactive Challenges only                      |

If a visitor passes an Interactive Challenge (highest security level), then the `cf_clearance` cookie indicates this to the origin and allows the visitor to bypass any other Challenge on the website, whether it is a Non-Interactive Challenge, a Managed Challenge, or another Interactive Challenge for as long as the cookie is valid.

If a visitor receives a `cf_clearance` cookie on a page that uses a WAF rule with Managed or Non-Interactive Challenge (lower security levels), then encountering a different page with a higher security clearance level Challenge will prompt them to solve the challenge again.

The original `cf_clearance` cookie that was issued to the visitor from a lower security clearance level challenge will be replaced with the new `cf_clearance` cookie from a higher security clearance level challenge.

## Pre-clearance support in Turnstile

Pre-clearance in [Turnstile](https://developers.cloudflare.com/turnstile/) allows websites to streamline user experiences by using `cf_clearance` cookies. The `cf_clearance` cookie enables visitors to bypass WAF Challenges on all subsequent requests on the zone, including API requests, based on the security clearance level set by the customer. This can be particularly useful for trusted visitors, enhancing usability while maintaining security.

By default, Turnstile issues a one-time use token to the visitor when they solve a challenge via the widget. You must [validate the token](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/) by making a server-side call to the Siteverify API.

Warning

It is critical to enforce Turnstile tokens with the Siteverify API. The Turnstile token could be invalid, expired, or already redeemed. Not verifying the token will leave major vulnerabilities in your implementation.

You **must** call Siteverify to complete your Turnstile configuration. Otherwise, it is incomplete and will result in zeroes for token validation when viewing your metrics in [Turnstile Analytics](https://developers.cloudflare.com/turnstile/turnstile-analytics/).

Note

The clearance token cannot be used again.

| Challenge type   | Issued clearance                                         |
| ---------------- | -------------------------------------------------------- |
| Challenge Page   | cf\_clearance cookie (default)                           |
| Turnstile widget | Token (default) cf\_clearance cookie (optional addition) |

When you enable pre-clearance support on Turnstile, a `cf_clearance` cookie is issued to the visitor in addition to the default Turnstile token.

You can integrate Cloudflare Challenges by allowing Turnstile to issue a `cf_clearance` cookie as pre-clearance to your visitor. The pre-clearance level is set upon widget creation or widget modification using the Turnstile API's clearance\_level. Possible values for the configuration are:

* `interactive`
* `managed`
* `jschallenge`
* `no_clearance`

All widgets have pre-clearance mode set to `false` and the security clearance is set to `no_clearance` by default.

For Enterprise customers eligible to enable widgets without any pre-configured hostnames, Cloudflare recommends issuing pre-clearance cookies on widgets where at least one hostname is specified and is the same as the zone that you want to integrate with Turnstile.

Refer to the [blog post ↗](https://blog.cloudflare.com/integrating-turnstile-with-the-cloudflare-waf-to-challenge-fetch-requests) for more details on how pre-clearance works with WAF.

### Pre-clearance level options

**Interactive** (High) `interactive`

Allows a user with a clearance cookie to not be challenged by Non-Interactive Challenge, Managed Challenge, or Interactive Challenge Firewall Rules.

**Managed** (Medium) `managed`

Allows a user with a clearance cookie to not be challenged by Non-Interactive Challenge or Managed Challenge Firewall Rules.

**Non-interactive** (Low) `jschallenge`

Allows a user with a clearance cookie to not be challenged by Non-Interactive Challenge Firewall Rules.

### Clearance cookie duration

Clearance cookies generated by the Turnstile widget will be valid for the time specified by the zone-level Challenge Passage value. To configure the Challenge Passage setting, refer to [Challenge Passage](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/challenge-passage/).

### Setup

To enable pre-clearance, you must ensure that the hostname of the Turnstile widget matches the zone with the WAF rules. During the Turnstile configuration setup in the Cloudflare dashboard, you have access to a list of registered zones. Select the appropriate hostname from this list.

The prerequisite is crucial for pre-clearance to function properly. If set up correctly, visitors who successfully solve Turnstile will receive a cookie with the security clearance level set by the customer. When encountering a WAF challenge on the same zone, they will bypass additional challenges for the configured clearance level and below.

For more details on managing hostnames, refer to the [Hostname Management documentation](https://developers.cloudflare.com/turnstile/additional-configuration/hostname-management/).

Note

[JavaScript detections](https://developers.cloudflare.com/bots/additional-configurations/javascript-detections/) are stored in the `cf_clearance` cookie.

The `cf_clearance` cookie cannot exceed the maximum size of 4096 bytes.

#### Enable pre-clearance on a new site

1. In the Cloudflare dashboard, go to the **Turnstile** page.  
[ Go to **Turnstile** ](https://dash.cloudflare.com/?to=/:account/turnstile)
2. Select **Add widget**.
3. Under **Would you like to opt for pre-clearance for this site?** select **Yes**.
4. Choose the pre-clearance level from the select box.
5. Select **Create**.

#### Enable pre-clearance on an existing site

1. In the Cloudflare dashboard, go to the **Turnstile** page.  
[ Go to **Turnstile** ](https://dash.cloudflare.com/?to=/:account/turnstile)
2. Go to the existing widget or site and select **Settings**.
3. Under **Would you like to opt for pre-clearance for this site?** select **Yes**.
4. Choose the pre-clearance level from the select box.
5. Select **Update**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/concepts/clearance/","name":"Clearance"}}]}
```

---

---
title: How Challenges work
description: How Cloudflare issues challenges through WAF rules, Bot Management, and Bot Fight Mode.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# How Challenges work

Challenges can be issued in three primary ways depending on which Cloudflare products or features are in use. Each method is designed to balance security with seamless visitor experience.

| Product                                                                                                                                                                                                                                                                                 | Challenge type(s)                                                                                                               |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| [WAF](https://developers.cloudflare.com/waf/) ([custom rules](https://developers.cloudflare.com/waf/custom-rules/), [rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/), [IP access rules](https://developers.cloudflare.com/waf/tools/ip-access-rules/)) | [Interstitial Challenge Page](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/)         |
| [Bot Management](https://developers.cloudflare.com/bots/get-started/bot-management/)                                                                                                                                                                                                    | [JavaScript Detections](https://developers.cloudflare.com/bots/additional-configurations/javascript-detections/)                |
| [Bot Fight Mode](https://developers.cloudflare.com/bots/get-started/bot-fight-mode/), [Super Bot Fight Mode](https://developers.cloudflare.com/bots/get-started/super-bot-fight-mode/)                                                                                                  | [Interstitial Challenge Page](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/)         |
| [Turnstile](https://developers.cloudflare.com/turnstile/)                                                                                                                                                                                                                               | Embedded widget                                                                                                                 |
| [HTTP DDoS attack protection](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/)                                                                                                                                                                                 | Any Challenge                                                                                                                   |
| [Under Attack Mode](https://developers.cloudflare.com/fundamentals/reference/under-attack-mode/)                                                                                                                                                                                        | [Managed Challenge](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/#managed-challenge) |

Challenge Pages and Turnstile rely on the same underlying mechanism to issue challenges to your website or application's visitors.

JavaScript Detections is an optional feature within [Bot Management](https://developers.cloudflare.com/bots/get-started/bot-management/). When enabled, Cloudflare injects a JavaScript snippet into HTML responses to gather client-side signals. Unlike Challenge Pages, JavaScript Detections runs on every HTML request without pausing or interrupting the visitor. It populates a pass/fail result (`cf.bot_management.js_detection.passed`) that you can then act on using a [WAF custom rule](https://developers.cloudflare.com/waf/custom-rules/).

---

## Available challenges

Refer to the following pages for more information on the different challenge types:

* [Interstitial Challenge Pages](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/)
* [Turnstile](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/turnstile/)
* [JavaScript Detections](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/javascript-detections/)

---

## Limitations

Cloudflare Challenges cannot support the following:

* [Browser extensions](https://developers.cloudflare.com/cloudflare-challenges/reference/supported-browsers/#browser-extensions) that modify the browser's `User-Agent` value or Web APIs such as `Canvas` and `WebGL`.
* Implementations where a domain serves a challenge page originally requested for another domain.
* Challenge Pages cannot be embedded in cross-origin iframes.
* Client software where the solve request of a Managed Challenge comes from a different IP than the original IP a Challenge request was issued to. For example, if you receive the Challenge from one IP and solve it using another IP, the solve is not valid and you may encounter a Challenge loop.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/concepts/how-challenges-work/","name":"How Challenges work"}}]}
```

---

---
title: Challenge solve rate (CSR)
description: Measure the percentage of issued challenges that visitors solve successfully.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Challenge solve rate (CSR)

The Challenge solve rate (CSR) is the percentage of issued challenges — Non-Interactive Challenge, Managed Challenge, or Interactive Challenge actions — that were solved.

Every challenge involves two separate events:

* **Challenge trigger**: The original request matches a WAF rule with a challenge action. Cloudflare issues a challenge to the visitor's browser.
* **Challenge solved**: The visitor's browser completes the challenge and sends back a validated response. This event is logged as challenge Solved.

Most automated traffic abandons immediately upon encountering the challenge script and never reaches the second event. This is why the count of unsolved challenges is typically very large — those abandonments count as failures in the formula.

```

CSR = number of challenges solved / number of challenges issued


```

CSR indicates the false positive percentage of a rule. A high CSR means a large share of issued challenges were solved by real visitors, which may indicate the rule is matching too much legitimate traffic. Use CSR to evaluate whether your rule's criteria or action needs adjustment.

You can find the CSR of a rule by going to its corresponding dashboard page:

* [  New dashboard ](#tab-panel-6867)
* [ Old dashboard ](#tab-panel-6868)

For [custom rules](https://developers.cloudflare.com/waf/custom-rules/) or [rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/), go to your zone > **Security** \> **Security rules**.

* For [custom rules](https://developers.cloudflare.com/waf/custom-rules/), go to your zone > **Security** \> **WAF** \> **Custom rules**.
* For [rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/), go to your zone > **Security** \> **WAF** \> **Rate limiting rules**.

---

## Challenge actions in Security Events

If you find a Challenge Solved action, such as `[js]challengeSolved` or `challengeSolved`, in your Security Events that does not match the underlying rule criteria, it is because this action refers to the successful mitigation of a previous request — not a re-match of the original rule.

The parameters of the solved request may no longer match the original rule's expression. For example, if a challenge was issued due to a low bot score, the score for the solved request may have already changed to a non-suspicious value upon successful verification.

The Challenge Solved action is an informative signal that a previously issued challenge was answered, allowing the visitor's traffic to proceed.

---

## Failed Challenges

You will not find a dedicated metric for failed challenges in Security Analytics because Cloudflare calculates failure indirectly, based on the difference between challenges issued and challenges solved.

The system views any issued challenge that does not result in a successful clearance cookie as a failure. This is why the number of failed challenges may appear exceptionally high: the majority of issued challenges are never completed.

The official calculation for failures is:

```

Failed Challenges = Total Challenges Issued − Total Challenges Solved


```

The large number of unmatched challenges is primarily due to automated traffic (bots or scrapers) that abandon the process immediately upon encountering the initial challenge script.

Key reasons a challenge may be issued but never solved:

* The visitor gives up on the challenge or navigates away from the page.
* The visitor attempts to solve the challenge but cannot provide a valid answer.
* The system receives an invalid or malformed answer from the client.
* The script environment (often a bot's controlled browser) fails to run the necessary client-side checks.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/reference/challenge-solve-rate/","name":"Challenge solve rate (CSR)"}}]}
```

---

---
title: Private Access Tokens (PAT)
description: How Private Access Tokens reduce challenge steps for visitors with valid tokens.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Private Access Tokens (PAT)

When a visitor is presented with a Challenge Page, Cloudflare evaluates various signals - including the presence of a Private Access Token (PAT) - to decide which challenges to issue. If a visitor presents a valid token, certain challenges are not issued, which reduces the number of steps required to pass.

A PAT does not automatically solve a challenge or let a visitor bypass the Challenge Page. The visitor still encounters the Challenge Page regardless of whether they have a valid PAT.

While some challenges require interactivity, most challenges served are invisible to the visitor.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/reference/private-access-tokens/","name":"Private Access Tokens (PAT)"}}]}
```

---

---
title: Supported browsers
description: Browser compatibility for challenge pages, Turnstile, and JavaScript detections.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Supported browsers

Cloudflare can challenge your visitors in various ways. They can be challenged by [Challenge Pages](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/), [Turnstile](https://developers.cloudflare.com/turnstile/), or by [JavaScript Detections (JSD) in Bot Management](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/javascript-detections/). This document lays out the supported browsers across all of these challenge methods. When your website or application presents a challenge, your visitors receive either a Non-interactive or an Interactive Challenge.

Cloudflare is committed to ensuring our challenges work with as many browsers as possible, but there are limitations that you should be aware of.

## Overview

Cloudflare Challenges are designed to be compatible with any desktop and mobile browser. If your visitors are using an up-to-date version of a browser listed below, they will receive and be able to solve challenges without any issues. The following is a non-exclusive list of browsers supported by Cloudflare Challenges. Browsers not listed on this list are supported on a best-effort basis.

### Supported browsers

The following browsers are officially supported and tested.

Google Chrome (desktop and mobile)

* Current version and two previous major versions
* Chromium-based browsers and Chromium-based browsers that track the current Chrome stable version

Warning

Beta, Dev, Canary, Nightly, or other unreleased builds are not officially supported.

Mozilla Firefox

* Current version and two previous major versions
* Extended Support Release (ESR) versions are supported

Safari

* Current version and two previous major versions
* iOS Safari on current iOS version and two previous major versions

Microsoft Edge

* Current version and two previous major versions

Samsung Internet Browser

* Current version and two previous major versions

### Limited browser support

The following browsers and environments have limited support and may experience occasional issues.

* Internet Explorer is no longer supported.
* Browsers or operating systems that are more than five years old or have not received security updates in over two years.
* Custom or heavily modified browser engines, webviews, or embedded browsers.

Note

If your visitors encounter issues using these browsers, we recommend upgrading to a more current browser for the best experience.

### Unsupported browsers

The following environments are not supported.

* Command-line tools such as `wget`, `curl`, or others that lack JavaScript execution capabilities required for Cloudflare Challenges.
* Headless browsers like headless Chrome, headless Firefox, PhantomJS, or others. Challenges are specifically designed to identify and block headless browser traffic. Automation tools and scripts that use headless browsers are not supported.
* Browser automation frameworks such as Selenium, Puppeteer, Playwright, or others that are considered automated traffic will be blocked by challenges.

## Common issues

### Browser extensions

Browser extensions can interfere with challenges in several ways.

* Ad blockers and content blockers may prevent challenge scripts from loading properly or block communication with Cloudflare's validation servers.
* Privacy-focused extensions like script blockers, fingerprinting protection, or canvas blockers can interfere with the challenge verification process.
* VPN or proxy extensions might trigger additional security checks or cause IP address inconsistencies.
* Browser automation tools are often detected as potential bots and may cause challenge failures.

Note

If challenges consistently fail, try temporarily disabling extensions and reload the page.

### Device emulation and developer tools

Challenges are designed to distinguish between real human users and automated traffic. When device emulation is enabled (such as through browser developer tools), it can trigger bot detection mechanisms.

* Mobile device emulation in desktop browsers often uses distinctive characteristics that differ from real mobile devices.
* Developer tools may modify browser behavior or expose debugging information that changes how challenges operate.
* Automation frameworks like Selenium, Puppeteer, or Playwright are specifically detected as non-human traffic.

Note

For developers testing applications, we recommend using real devices rather than emulated environments when possible.

If you must use emulation, be aware that challenges may be more difficult to pass, and do not reflect the real experience on mobile devices.

### WebViews and in-app browsers

Challenges may behave differently depending on embedded browser contexts.

* WebViews in mobile applications may have limited functionality compared to full browsers
* In-app browsers often have restricted JavaScript capabilities
* Email client preview windows typically cannot complete Interactive Challenges

## Troubleshooting

If your visitors consistently experience challenge issues, refer to [Challenge solve issues](https://developers.cloudflare.com/cloudflare-challenges/troubleshooting/challenge-solve-issues/) for additional troubleshooting information.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/reference/supported-browsers/","name":"Supported browsers"}}]}
```

---

---
title: Supported languages
description: Languages supported by Cloudflare challenge pages, detected via navigator.language.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Supported languages

## Multi-language support

Cloudflare Challenges can detect multiple languages and display the localized challenge experience, which is determined by `navigator.language` value. The [Navigator.language read-only property ↗](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/language) returns a string representing the preferred language of the user, usually the language of the browser user interface.

For language support specific to Challenge Pages, refer to the table below.

| Language                      | Language code(4 letters) | Language code(2 letters) |
| ----------------------------- | ------------------------ | ------------------------ |
| Arabic (Egypt)                | ar-eg                    | ar                       |
| Chinese (Simplified, China)   | zh-cn                    | zh                       |
| Chinese (Traditional, Taiwan) | zh-tw                    | \--                      |
| Dutch (Netherlands)           | nl-nl                    | nl                       |
| English (United States)       | en-us                    | en                       |
| French (France)               | fr-fr                    | fr                       |
| German (Germany)              | de-de                    | de                       |
| Indonesian (Indonesia)        | id-id                    | id                       |
| Italian (Italy)               | it-it                    | it                       |
| Japanese (Japan)              | ja-jp                    | ja                       |
| Korean (Korea)                | ko-kr                    | ko                       |
| Persian                       | \--                      | fa                       |
| Polish (Poland)               | pl-pl                    | pl                       |
| Portuguese (Brazil)           | pt-br                    | pt                       |
| Russian (Russia)              | ru-ru                    | ru                       |
| Spanish (Spain)               | es-es                    | es                       |
| Turkish (Turkey)              | tr-tr                    | tr                       |

### Turnstile language support

For language support specific to Turnstile, refer to the [Turnstile documentation](https://developers.cloudflare.com/turnstile/reference/supported-languages/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-challenges/","name":"Challenges"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-challenges/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-challenges/reference/supported-languages/","name":"Supported languages"}}]}
```

---

---
title: Cloudflare DDoS Protection
description: Detect and mitigate DDoS attacks automatically across all Cloudflare plans.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare DDoS Protection

Detect and mitigate distributed denial-of-service (DDoS) attacks automatically.

 Available on all plans 

Cloudflare automatically detects and mitigates [distributed denial-of-service (DDoS) attacks](https://www.cloudflare.com/learning/ddos/what-is-a-ddos-attack/) via our autonomous DDoS systems.

These systems include multiple dynamic mitigation rules exposed as [DDoS attack protection managed rulesets](https://developers.cloudflare.com/ddos-protection/managed-rulesets/). You can customize the mitigation rules included in these rulesets to optimize and tailor the protection to your needs.

---

## Features

###  Managed rulesets 

Protect against a variety of DDoS attacks across layers 3/4 (network layer) and layer 7 (application layer) of the OSI model.

[ Use Managed rulesets ](https://developers.cloudflare.com/ddos-protection/managed-rulesets/) 

###  Adaptive DDoS Protection 

Get increased protection against sophisticated DDoS attacks on layer 7 and layers 3/4.

[ Use Adaptive DDoS Protection ](https://developers.cloudflare.com/ddos-protection/managed-rulesets/adaptive-protection/) 

###  Advanced TCP Protection 

Detect and mitigate sophisticated out-of-state TCP attacks such as randomized and spoofed ACK floods, or SYN and SYN-ACK floods.

[ Use Advanced TCP Protection ](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/) 

###  Advanced DNS Protection 

Protect against DNS-based DDoS attacks, specifically sophisticated and fully randomized DNS attacks such as random prefix attacks.

[ Use Advanced DNS Protection ](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-dns-protection/) 

###  Programmable Flow Protection 

Deploy custom eBPF packet logic across Cloudflare's network to inspect and mitigate DDoS attacks against UDP-based Layer 7 protocols.

[ Use Programmable Flow Protection ](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/programmable-flow-protection/) 

---

## Availability

| Free                                                   | Pro                                                                                      | Business                                                                                 | Enterprise                                                                               | Enterprise with Advanced DDoS Protection add-on                                          |                                                                                          |
| ------------------------------------------------------ | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| Availability                                           | Yes                                                                                      | Yes                                                                                      | Yes                                                                                      | Yes                                                                                      | Yes                                                                                      |
| Standard, unmetered DDoS protection (layers 3-7)       | Yes                                                                                      | Yes                                                                                      | Yes                                                                                      | Yes                                                                                      | Yes                                                                                      |
| HTTP DDoS attack protection                            | Yes                                                                                      | Yes                                                                                      | Yes                                                                                      | Yes                                                                                      | Yes                                                                                      |
| Network-layer (L3/4) DDoS attack protection            | Yes                                                                                      | Yes                                                                                      | Yes                                                                                      | Yes                                                                                      | Yes                                                                                      |
| Managed rules customization                            | Yes                                                                                      | Yes                                                                                      | Yes                                                                                      | Yes, with Log action                                                                     | Expression fields & multi-rule support                                                   |
| Proactive false positive detection for new rules       | No                                                                                       | No                                                                                       | No                                                                                       | Yes                                                                                      | Yes                                                                                      |
| Adaptive DDoS protection                               | Only error adaptive rules                                                                | Only error adaptive rules                                                                | Only error adaptive rules                                                                | Only error adaptive rules                                                                | All adaptive rules                                                                       |
| Traffic profiling signals for adaptive DDoS protection | Error rates only                                                                         | Error rates only                                                                         | Error rates & historical trends                                                          | Error rates & historical trends                                                          | Error rates & historical trends, client country, user agent, query string, ML-scores     |
| Advanced TCP Protection                                | Available to [Magic Transit](https://developers.cloudflare.com/magic-transit/) customers | Available to [Magic Transit](https://developers.cloudflare.com/magic-transit/) customers | Available to [Magic Transit](https://developers.cloudflare.com/magic-transit/) customers | Available to [Magic Transit](https://developers.cloudflare.com/magic-transit/) customers | Available to [Magic Transit](https://developers.cloudflare.com/magic-transit/) customers |
| Advanced DNS Protection                                | Available to [Magic Transit](https://developers.cloudflare.com/magic-transit/) customers | Available to [Magic Transit](https://developers.cloudflare.com/magic-transit/) customers | Available to [Magic Transit](https://developers.cloudflare.com/magic-transit/) customers | Available to [Magic Transit](https://developers.cloudflare.com/magic-transit/) customers | Available to [Magic Transit](https://developers.cloudflare.com/magic-transit/) customers |
| Number of ruleset overrides allowed                    | 1                                                                                        | 1                                                                                        | 1                                                                                        | 1                                                                                        | 10                                                                                       |
| Alerts                                                 | Yes                                                                                      | Yes                                                                                      | Yes                                                                                      | Yes                                                                                      | Advanced alerts with filtering                                                           |

---

## Related products

**[Spectrum](https://developers.cloudflare.com/spectrum/)** 

Provides security and acceleration for any TCP or UDP based application.

**[Magic Transit](https://developers.cloudflare.com/magic-transit/)** 

A network security and performance solution that offers DDoS protection, traffic acceleration, and more for on-premise, cloud-hosted, and hybrid networks.

**[Web Application Firewall (WAF)](https://developers.cloudflare.com/waf/)** 

Get automatic protection from vulnerabilities and the flexibility to create custom rules.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}}]}
```

---

---
title: Get started
description: Set up and fine-tune DDoS protection for your zones, Spectrum apps, and Magic Transit prefixes.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

## Free, Pro, and Business plans

The DDoS Attack Protection managed rulesets provided by Cloudflare are enabled by default on zones onboarded to Cloudflare, IP applications onboarded to Spectrum, and IP Prefixes onboarded to Magic Transit.

In some situations, the default protection offered by DDoS rules may need to be fine-tuned to your specific situation. You may also want to configure additional protection using other Cloudflare products.

### Adjust the provided DDoS rules

If one or more DDoS rules provided by Cloudflare affects legitimate traffic, you can adjust them so that they do not perform any mitigation action against this kind of traffic. Follow the steps in [handling a false positive](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/override-examples/#legitimate-traffic-is-incorrectly-identified-as-an-attack-and-causes-a-false-positive) to reduce the sensitivity level of one or more DDoS rules and allow incoming legitimate traffic.

### Configure additional protection

To configure additional protection against DDoS attacks, refer to the related Cloudflare products listed in [Network-layer DDoS Attack Protection](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/#related-cloudflare-products) and [HTTP DDoS Attack Protection](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/#related-cloudflare-products).

## Enterprise plan

Cloudflare's DDoS protection systems automatically detect and mitigate DDoS attacks. Additionally, the systems may flag suspiciously-looking incoming traffic from legacy applications, Internet services, or faulty client applications as malicious and apply mitigation actions. If the traffic is in fact legitimate, the mitigation actions can cause service disruptions and outages in your Internet properties.

To prevent this situation, Cloudflare recommends that you perform these steps to get started:

1. Set the ruleset actions for all the [DDoS Attack Protection managed rulesets](https://developers.cloudflare.com/ddos-protection/managed-rulesets/) to _Log_.
2. Analyze the flagged traffic.
3. Adjust the sensitivity or action of individual managed ruleset rules, if required.
4. Switch ruleset actions from _Log_ back to the default.

### Prerequisites

You must have one of the following:

* [A zone onboarded to Cloudflare](https://developers.cloudflare.com/dns/zone-setups/full-setup/) but without updated DNS records.
* [An IP application onboarded to Spectrum](https://developers.cloudflare.com/spectrum/get-started/).
* [An IP Prefix onboarded to Magic Transit](https://developers.cloudflare.com/magic-transit/get-started/).

### 1\. Configure ruleset actions to Log

Note

The _Log_ action is only available to Enterprise customers.

1. [Configure all the rules in the HTTP DDoS Attack Protection managed ruleset](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/configure-dashboard/#access), setting their action to _Log_.
2. [Configure all the rules in the Network-layer DDoS Attack Protection managed ruleset](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/configure-dashboard/#create-a-ddos-override), setting the action to _Log_.

Alternatively, if you are using the API, define an override at the ruleset level to set the action of all managed ruleset rules to `log` by following these instructions:

* [Configure an override for the HTTP DDoS Attack Protection managed ruleset](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/configure-api/#configure-an-override-for-the-http-ddos-attack-protection-managed-ruleset)
* [Configure an override for the Network-layer DDoS Attack Protection managed ruleset](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/configure-api/#configure-an-override-for-the-network-layer-ddos-attack-protection-managed-ruleset)

### 2\. Review flagged traffic

1. Go to your [analytics dashboard](https://developers.cloudflare.com/ddos-protection/reference/analytics/) (the exact dashboard depends on your Cloudflare services).
2. Apply one or more filters, if required, and identify any rules that would have blocked legitimate traffic if _Log_ mode were disabled. Take note of the rule IDs.

### 3\. Customize managed ruleset rules

Customize the specific managed ruleset rules you identified, changing their sensitivity or their action, using the Cloudflare dashboard or using the API.

If you are using the Cloudflare dashboard, refer to:

* [Configure HTTP DDoS Attack Protection in the dashboard](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/configure-dashboard/)
* [Configure Network-layer DDoS Attack Protection in the dashboard](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/configure-dashboard/)

If you are using the API, refer to:

* [Configure HTTP DDoS Attack Protection via API](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/configure-api/)
* [Configure Network-layer DDoS Attack Protection via API](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/configure-api/)

When using the API, ensure that you add any required rule overrides without removing the ruleset override you configured in [Step 1](#1-configure-ruleset-actions-to-log).

### 4\. Switch ruleset actions back to the default

Revert the change you did in [Step 1](#1-configure-ruleset-actions-to-log), changing the action of each managed ruleset rule back to _Default_ in **Ruleset action**.

Alternatively, if you are using the API, [remove the override](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/configure-api/#configure-an-override-for-the-http-ddos-attack-protection-managed-ruleset) you previously configured at the ruleset level for each managed ruleset. Ensure that you only remove the ruleset override and not any of the rule overrides you may have configured in [Step 3](#3-customize-managed-ruleset-rules).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/get-started/","name":"Get started"}}]}
```

---

---
title: About
description: How Cloudflare DDoS protection detects and mitigates attacks across network layers.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# About

Cloudflare provides unmetered and unlimited [distributed denial-of-service (DDoS)](https://www.cloudflare.com/learning/ddos/what-is-a-ddos-attack/) protection at layers 3, 4, and 7 to all customers on all plans and services.

The protection is enabled by Cloudflare's [Autonomous DDoS Protection Edge](https://developers.cloudflare.com/ddos-protection/about/components/#autonomous-edge), which automatically detects and mitigates DDoS attacks.

The Autonomous Edge includes multiple dynamic mitigation rules exposed as [managed rulesets](https://developers.cloudflare.com/ddos-protection/managed-rulesets/), which provide comprehensive protection against a variety of DDoS attacks across layers 3/4 and layer 7 of the OSI model.

[Adaptive DDoS Protection](https://developers.cloudflare.com/ddos-protection/managed-rulesets/adaptive-protection/) also learns your unique traffic patterns and adapts to them to provide better protection against sophisticated DDoS attacks on layer 7 and layers 3/4\. Your Internet properties can be secured from sophisticated TCP and DNS DDoS attacks using [Advanced DDoS Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/) that leverages stateful inspection and traffic profiling.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/about/","name":"About"}}]}
```

---

---
title: Attack coverage
description: DDoS attack types covered by Cloudflare managed rulesets at layers 3, 4, and 7.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Attack coverage

The [DDoS Attack Protection managed rulesets](https://developers.cloudflare.com/ddos-protection/managed-rulesets/) provide protection against a variety of DDoS attacks across L3/4 (layers 3/4) and L7 of the OSI model. Cloudflare constantly updates these managed rulesets to improve the attack coverage, increase the mitigation consistency, cover new and emerging threats, and ensure cost-efficient mitigations.

[Advanced TCP Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/), [Advanced DNS Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-dns-protection/), and [Programmable Flow Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/programmable-flow-protection/) are available to Magic Transit customers. Advanced TCP Protection provides additional protection against sophisticated TCP-based DDoS attacks. Advanced DNS Protections protects against sophisticated and fully randomized DNS attacks. Programmable Flow Protection mitigates UDP-based attacks by executing a customer-defined program.

As a general guideline, various Cloudflare products operate on different open systems interconnection (OSI) layers and you are protected up to the layer on which your service operates. You can customize the DDoS settings on the layer in which you onboarded. For example, since the CDN/WAF service is a Layer 7 (HTTP/HTTPS) service, Cloudflare provides protection from DDoS attacks on L7 downwards, including L3/4 attacks.

Note

For Magic Transit customers, Cloudflare provides some L7 protection with a L3 service (like the Advanced DNS Protection system that is available for Magic Transit customers. DNS is considered a L7 protocol).

The following table includes a sample of covered attack vectors:

| OSI Layer   | Ruleset / Feature                                                                                                                                            | Example of covered DDoS attack vectors                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| L3/4        | [Network-layer DDoS Attack Protection](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/)                                          | ACK floodsBitTorrent reflection attackCarpet Bombing attacksCHARGEN reflection attacksDNS amplification attackDNS Garbage FloodDNS NXDOMAIN floodDNS Query floodDTLS amplification attacksESP floodGRE floodsICMP flood attackJenkins amplification attacksLantronix reflection attacksmDNS DDoS attacksMemcached amplification attacksMirai and Mirai-variant L3/4 attacksMSSQL reflection attacksNetBios DDoS attacksOut of state TCP attacksProtocol violation attacksQUIC flood attackQuote of the Day (QOTD) reflection attacksRST floodSIP attacksSNMP flood attackSPSS reflection attacksSSDP reflection attacksSYN floodsSYN-ACK reflection attackTeamSpeak 3 floodsUbiquity reflection attacksUDP flood attackVxWorks DDoS attacksFor more DNS protection options, refer to [Getting additional DNS protection](https://developers.cloudflare.com/ddos-protection/about/attack-coverage/#getting-additional-dns-protection). |
| L3/4        | [Advanced TCP Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/) [1](#user-content-fn-1) | Fully randomized and spoofed ACK floods, SYN floods, SYN-ACK reflection attacks, and other sophisticated TCP-based DDoS attacks                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| L7 (DNS)    | [Advanced DNS Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-dns-protection/) [1](#user-content-fn-1) | Sophisticated and fully randomized DNS attacks, including Water Torture attacks, Random-prefix attacks, and DNS laundering attacks.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| L7 (HTTP/S) | [HTTP DDoS Attack Protection](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/)                                                      | Cache busting attacksCarpet Bombing attacksHTTP Continuation floodHTTP flood attackHTTP/2 MadeYouResetHTTP/2 Rapid ResetHULK attackKnown DDoS botnetsLOIC attackMirai and Mirai-variant HTTP attacksSlowloris attackTLS/SSL exhaustion attacksTLS/SSL negotiation attacksWordPress pingback attack                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |

## Footnotes

1. Available to Magic Transit customers. [↩](#user-content-fnref-1) [↩2](#user-content-fnref-1-2)

## Getting additional DNS protection

The Network-layer DDoS Attack Protection managed ruleset provides protection against some types of DNS attacks.

Magic Transit customers have access to [Advanced DNS Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-dns-protection/) Beta. Other customers might consider the following options:

* Use Cloudflare as your authoritative DNS provider ([primary DNS](https://developers.cloudflare.com/dns/zone-setups/full-setup/) or [secondary DNS](https://developers.cloudflare.com/dns/zone-setups/zone-transfers/cloudflare-as-secondary/)).
* If you are running your own nameservers, use [DNS Firewall](https://developers.cloudflare.com/dns/dns-firewall/) to get additional protection against DNS attacks like random prefix attacks.

## Email-based attacks

DDoS Protection covers web and network protocols, including TCP, UDP, DNS, and HTTP/S. It does not cover email protocols such as SMTP, IMAP, or POP3.

For protection against email-borne threats such as phishing and malware, refer to [Email Security](https://developers.cloudflare.com/email-security/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/about/","name":"About"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/about/attack-coverage/","name":"Attack coverage"}}]}
```

---

---
title: Main components
description: Key components of Cloudflare DDoS protection, including managed rulesets and advanced systems.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Main components

![Diagram with the main components providing protection against DDoS attacks at Cloudflare](https://developers.cloudflare.com/_astro/ddos-diagram.DygBAs9m_2nhC7u.webp) 

## Autonomous Edge

The Cloudflare Autonomous Edge is powered by the denial-of-service daemon (`dosd`), which is a home-grown software-defined system. The flow tracking daemon, `flowtrackd`, is our stateful mitigation platform alongside `dosd`. A `dosd` instance runs in every single server in every one of [Cloudflare global network's data centers ↗](https://www.cloudflare.com/network/) around the world. These `dosd` instances can detect and mitigate DDoS attacks autonomously without requiring centralized consensus. Cloudflare users can configure this system through [DDoS Attack Protection managed rulesets](https://developers.cloudflare.com/ddos-protection/managed-rulesets/).

Another component of Cloudflare's Autonomous Edge includes the [Advanced TCP Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/) system. This is Cloudflare's TCP state tracking machine for detecting and mitigating the most randomized and sophisticated TCP-based DDoS attacks in unidirectional routing topologies — such as the case of [Magic Transit](https://developers.cloudflare.com/magic-transit/). Advanced TCP Protection is able to identify the state of a TCP connection and then drops, challenges, or rate-limits packets that do not belong to a legitimate connection.

For more information, refer to our blog post [A deep-dive into Cloudflare's autonomous edge DDoS protection ↗](https://blog.cloudflare.com/deep-dive-cloudflare-autonomous-edge-ddos-protection/).

## Centralized DDoS protection system

Complementary to the Autonomous Edge, Cloudflare's entire global network is overwatched by a global version of `dosd`. This component protects Cloudflare's entire global network by detecting and mitigating globally distributed volumetric DDoS attacks.

The centralized systems run in Cloudflare's core data centers. They receive samples from every global network data center, analyze them, and automatically send mitigation instructions when detecting an attack. The system is also synchronized to each of our customers' web servers to identify their health and trigger any required mitigation actions.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/about/","name":"About"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/about/components/","name":"Main components"}}]}
```

---

---
title: How DDoS protection works
description: How Cloudflare analyzes traffic and applies autonomous mitigation at the network edge.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# How DDoS protection works

To detect and mitigate DDoS attacks, Cloudflare's autonomous edge and centralized DDoS systems analyze traffic samples out of path, which allows Cloudflare to asynchronously detect DDoS attacks without causing latency or impacting performance.

The analyzed samples include:

* **Packet fields** such as the source IP, source port, destination IP, destination port, protocol, TCP flags, sequence number, options, and packet rate.
* **HTTP request metadata** such as HTTP headers, user agent, query-string, path, host, HTTP method, HTTP version, TLS cipher version, and request rate.
* **HTTP response metrics** such as error codes returned by customers' origin servers and their rates.

Cloudflare uses a set of dynamic rules that scan for attack patterns, known attack tools, suspicious patterns, protocol violations, requests causing large amounts of origin errors, excessive traffic hitting the origin or cache, and additional attack vectors. Each rule has a predefined sensitivity level and default action that varies based on the rule's confidence that the traffic is indeed part of an attack.

Note

You can set an override expression for the [HTTP DDoS Attack Protection](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/override-expressions/) or [Network-layer DDoS Attack Protection](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/override-expressions/) managed ruleset to define a specific scope for sensitivity level or action adjustments.

Once attack traffic matches a rule, Cloudflare's systems will track that traffic and generate a real-time signature to surgically match against the attack pattern and mitigate the attack without impacting legitimate traffic. The rules are able to generate different signatures based on various properties of the attacks and the signal strength of each attribute. For example, if the attack is distributed — that is, originating from many source IPs — then the source IP field will not serve as a strong indicator, and the rule will not choose the source IP field as part of the attack signature. Once generated, the fingerprint is propagated as a mitigation rule to the most optimal location on the Cloudflare global network for cost-efficient mitigation. These mitigation rules are ephemeral and will expire shortly after the attack has ended, which happens when no additional traffic has been matched to the rule.

| Actions               | Description                                                                                             |
| --------------------- | ------------------------------------------------------------------------------------------------------- |
| Block                 | Matching requests are denied access to the site.                                                        |
| Managed Challenge     | Depending on the characteristics of a request, Cloudflare will choose an appropriate type of challenge. |
| Interactive Challenge | The client that made the request must pass an interactive Challenge.                                    |
| Log                   | Records matching requests in the Cloudflare Logs.                                                       |
| Use rule defaults     | Uses the default action that is pre-defined for each rule.                                              |

## Thresholds

Thresholds vary for each rule and there are different thresholds globally and per colocation. Within a rule, the traffic is fingerprinted and the thresholds are per fingerprint, and it is difficult to know ahead of time which rules, colocations, or fingerprints your traffic generates, so the threshold numbers are not necessarily valuable.

Instead, Cloudflare's DDoS Protection system provides the sensitivity adjustment. If you experience a false positive, you can decrease the sensitivity. You can also use the `Log` action to help find an appropriate sensitivity level. You can decrease the sensitivity while in `Log` mode until the rule no longer matches.

## Time to mitigate

* Immediate mitigation for Advanced TCP and DNS Protection systems.
* Up to three seconds on average for the detection and mitigation of L3/4 DDoS attacks at the edge using the Network-layer DDoS Protection Managed rules.
* Up to three seconds on average for the detection and mitigation of HTTP DDoS attacks at the edge using the HTTP DDoS Protection Managed rules.

## Data localization

To learn more about how DDoS protection works with data localization, refer to the Data Localization Suite [product compatibility](https://developers.cloudflare.com/data-localization/compatibility/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/about/","name":"About"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/about/how-ddos-protection-works/","name":"How DDoS protection works"}}]}
```

---

---
title: Managed rulesets
description: Pre-configured DDoS rulesets that protect against attacks at layers 3, 4, and 7.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Managed rulesets

The DDoS Attack Protection managed rulesets provide comprehensive protection against a [variety of DDoS attacks](https://developers.cloudflare.com/ddos-protection/about/attack-coverage/) across L3/4 (network layer) and L7 (application layer) of the [OSI model ↗](https://www.cloudflare.com/learning/ddos/glossary/open-systems-interconnection-model-osi/).

The available managed rulesets are:

* **[HTTP DDoS Attack Protection](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/)**  
   * This ruleset includes rules to detect and mitigate DDoS attacks over HTTP and HTTPS.
* **[Network-layer DDoS Attack Protection](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/)**  
   * This ruleset includes rules to detect and mitigate DDoS attacks on L3/4 of the OSI model such as UDP floods, SYN-ACK reflection attacks, SYN Floods, and DNS floods.

---

## Proactive false positive detection for new rules

Note

Only available on Business and Enterprise plans.

When Cloudflare creates a new managed rule, we check the rule impact against the traffic of Business and Enterprise zones while the rule is not blocking traffic yet.

If a [false positive](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/override-examples/#legitimate-traffic-is-incorrectly-identified-as-an-attack-and-causes-a-false-positive) is detected, we proactively reach out to the affected customers and help them make configuration changes (for example, to lower the sensitivity level of the new rule) before the rule starts mitigating traffic. This prevents the new rule from causing service disruptions and outages to your Internet properties.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}}]}
```

---

---
title: Adaptive DDoS Protection
description: Explore Cloudflare's Adaptive DDoS Protection, which learns traffic patterns to defend against sophisticated DDoS attacks on layers 3/4 and 7.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Adaptive DDoS Protection

Adaptive DDoS Protection learns your unique traffic patterns and adapts to them to provide better protection against sophisticated DDoS attacks on layer 7 and layers 3/4, depending on your subscribed Cloudflare services.

Adaptive DDoS Protection provides the following types of protection:

* **Adaptive DDoS Protection for Origins**: Detects and mitigates traffic that deviates from your site's origin errors profile.
* **Adaptive DDoS Protection for User-Agents**: Detects and mitigates traffic that deviates from the top User Agents seen by Cloudflare on the network. The User Agent profile is built from the entire Cloudflare network and not only from the customer's zone.
* **Adaptive DDoS Protection for Locations**: Detects and mitigates traffic that deviates from your site's geo-distribution profile. The profile is calculated from the rate for every client country and region, using the rates from the past seven days.
* **Adaptive DDoS Protection for Protocols**: Detects and mitigates traffic that deviates from your traffic's IP protocol profile. The profile is calculated as a global rate for each of your prefixes.

## Availability

Cloudflare Adaptive DDoS Protection is available to Enterprise customers according to the following table:

| Feature                           | Profiling dimension                   | WAF/CDN1 | Magic Transit /Spectrum BYOIP2 |
| --------------------------------- | ------------------------------------- | -------- | ------------------------------ |
| **HTTP Adaptive DDoS Protection** |                                       |          |                                |
| For Origins                       | Origin errors                         | Yes      | —                              |
| For User-Agents                   | User Agent(entire Cloudflare network) | Yes      | —                              |
| For Locations                     | Client IP country and region          | Yes      | —                              |
| **L3/4 Adaptive DDoS Protection** |                                       |          |                                |
| For Protocols                     | IP protocol                           | —        | Yes                            |
| For Protocols                     | Client IP country and Region for UDP  | —        | Yes                            |

1 _WAF/CDN customers on the Enterprise plan with the Advanced DDoS Protection subscription._

  
2 _Magic Transit and Spectrum BYOIP customers on an Enterprise plan._

## How it works

Adaptive DDoS Protection creates a traffic profile by looking at the maximum rates of traffic every day, for the past seven days. These profiles are recalculated every day, keeping the seven-day time window. Adaptive DDoS Protection stores the maximal traffic rates seen for every predefined dimension value (the profiling dimension varies for each rule). Every profile uses one dimension, such as the source country of the request, the user agent, and the IP protocol. Incoming traffic that deviates from your profile may be malicious.

To eliminate outliers, rate calculations only consider the 95th percentile rates (discarding the top 5% of the highest rates). Cloudflare requires a minimum amount of requests per second (rps) to build traffic profiles. HTTP Adaptive DDoS Protection rules also take into account Cloudflare's [Machine Learning (ML) models](https://developers.cloudflare.com/bots/concepts/bot-score/#machine-learning) to identify traffic that is likely automated.

Cloudflare may change the logic of these protection rules from time to time to improve them.

Note

HTTP Adaptive DDoS Protection rules calculate the traffic profile at the zone-level. Therefore, the HTTP Adaptive rules may be ineffective for an [SSL for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) zone shared by many of your customers' [custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/). The traffic profile would be created based on the varied and aggregated traffic of all of the various custom hostnames. It will not be accurate for an individual customer's hostname.

---

## View flagged traffic

To view traffic flagged by HTTP Adaptive DDoS Protection rules:

* [  New dashboard ](#tab-panel-7905)
* [ Old dashboard ](#tab-panel-7906)

1. In the Cloudflare dashboard, go to the **Security Analytics** page.  
[ Go to **Analytics** ](https://dash.cloudflare.com/?to=/:account/:zone/security/analytics)
2. Go to **Events**.
3. Filter by `Service equals HTTP DDoS` and by rule ID.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security** \> **Events**.
3. Filter by `Service equals HTTP DDoS` and by rule ID.

To view traffic flagged by L3/4 Adaptive DDoS Protection rules:

* [  New dashboard ](#tab-panel-7907)
* [ Old dashboard ](#tab-panel-7908)

1. In the Cloudflare dashboard, go to the **Security Analytics** page.  
[ Go to **Analytics** ](https://dash.cloudflare.com/?to=/:account/:zone/security/analytics)
2. Go to **Events**.
3. Filter by rule ID.

1. In the Cloudflare dashboard, go to the **Network analytics** page.  
[ Go to **Network analytics** ](https://dash.cloudflare.com/?to=/:account/networking-insights/analytics/network-analytics/transport-analytics)
2. Filter by rule ID.

You may also obtain information about flagged traffic through [Logpush](https://developers.cloudflare.com/logs/logpush/) or the [GraphQL API](https://developers.cloudflare.com/analytics/graphql-api/).

To determine if an adaptive rule fits your traffic in a way that will only mitigate attack traffic and will not cause false positives, review the traffic that is _Logged_ by the adaptive rules.

Note

You may not see any traffic matching the adaptive rules. This can be because there was no deviation from your traffic profile, so you may want to increase the time range and look for any _Logged_ traffic. Another reason why you may not see _Logged_ traffic by the adaptive rules is that there was not sufficient traffic volume to generate a traffic profile for your zone.

If you do see traffic that was _Logged_ by the adaptive rules, use the dashboard to determine if the traffic matches the characteristics of legitimate users or that of attack traffic. As each Internet property is unique, understanding if the traffic is legitimate requires your understanding of how your legitimate traffic looks. For example, the user agent, source country, headers, query string for HTTP requests, and protocols and ports for L3/4 traffic.

* In cases where you are certain that the rule is only flagging attack traffic, you should consider creating an override and enabling that rule with a [Managed Challenge](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/#managed-challenge) or `Block` action.
* In cases where you see legitimate traffic being flagged, you should lower the sensitivity level of the rule and observe the flagged traffic. You can continue reducing the sensitivity level until you reach a point where legitimate traffic is not flagged. Then, you should create an override to enable the rule with a mitigation action.
* If the rule is still flagging legitimate traffic you can consider using the expression filters to condition the rules to exclude certain types of traffic.

The default rule action for `log` with a sensitivity set to `high` will only show packets or requests with suspected attack traffic over internal `high` thresholds in your logs. For instance, if you set the threshold to `medium` or `low`, then only packets over those thresholds will be logged.

## Configure the rules

You can adjust the action and sensitivity of the Adaptive DDoS Protection rules. The default action is _Log_. Use this action to first observe what traffic is flagged before deciding on a mitigation action.

To configure a rule, refer to the instructions in the following pages:

* [Configure HTTP DDoS Attack Protection in the dashboard](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/configure-dashboard/) (for L7 rules)
* [Configure Network-layer DDoS Attack Protection in the dashboard](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/configure-dashboard/) (for L3/4 rules)

For more information on the available configuration parameters, refer to the following pages:

* For the (L7) DDoS protection rules for Origins, User-Agents, and Locations:  
[HTTP DDoS Attack Protection parameters](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/override-parameters/)
* For the (L3/4) DDoS protection rules for Protocols:  
[Network-layer DDoS Attack Protection parameters](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/override-parameters/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/adaptive-protection/","name":"Adaptive DDoS Protection"}}]}
```

---

---
title: HTTP DDoS Attack Protection
description: Explore HTTP DDoS Attack Protection rule categories, including botnets, unusual requests, and advanced features, to enhance your Cloudflare security.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# HTTP DDoS Attack Protection

The Cloudflare HTTP DDoS Attack Protection managed ruleset is a set of pre-configured rules used to match [known DDoS attack vectors](https://developers.cloudflare.com/ddos-protection/about/attack-coverage/) at layer 7 (application layer) on the Cloudflare global network. The rules match known attack patterns and tools, suspicious patterns, protocol violations, requests causing large amounts of origin errors, excessive traffic hitting the origin/cache, and additional attack vectors at the application layer.

Cloudflare updates the list of rules in the managed ruleset on a regular basis. Refer to the [changelog](https://developers.cloudflare.com/ddos-protection/change-log/http/) for more information on recent and upcoming changes.

The HTTP DDoS Attack Protection managed ruleset is always enabled — you can only customize its behavior.

The HTTP DDoS Attack Protection managed ruleset provides users with increased observability into L7 DDoS attacks mitigated by Cloudflare, informing users of ongoing or past attacks. The [Security Events dashboard](https://developers.cloudflare.com/waf/analytics/security-events/), available at **Security** \> **Events**, will display information about the top HTTP DDoS managed rules.

## Ruleset configuration

If you are expecting large spikes of legitimate traffic, consider customizing your DDoS protection settings to avoid [false positives](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/override-examples/#legitimate-traffic-is-incorrectly-identified-as-an-attack-and-causes-a-false-positive), where legitimate traffic is falsely identified as attack traffic and blocked/challenged.

You can adjust the behavior of the rules in the managed ruleset by modifying the following parameters:

* The performed **action** when an attack is detected.
* The **sensitivity level** of attack detection mechanisms.

Notes

* Certain actions or sensitivity levels may not be available to all Cloudflare plans.
* Currently, you can only define account-level configurations (or overrides) for the HTTP DDoS Attack Protection managed ruleset via API.

To adjust rule behavior, do one of the following:

* [Configure the managed ruleset in the Cloudflare dashboard](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/configure-dashboard/).
* [Configure the managed ruleset via API](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/configure-api/).
* [Configure the managed ruleset using Terraform](https://developers.cloudflare.com/terraform/additional-configurations/ddos-managed-rulesets/#example-configure-http-ddos-attack-protection).

For more information on the available configuration parameters, refer to [Managed ruleset parameters](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/override-parameters/).

## Origin Protect rules

Cloudflare HTTP DDoS Protection can also initiate mitigation based on the origin health. [Adaptive DDoS Protection for Origins](https://developers.cloudflare.com/ddos-protection/managed-rulesets/adaptive-protection/) detects and mitigates traffic that deviates from your site's origin errors profile. Floods of requests that cause a high number of zone errors (default sensitivity level is 1,000 errors per second) can initiate mitigation to alleviate the strain on the zone.

| Rule ID                          | Description                                           |
| -------------------------------- | ----------------------------------------------------- |
| dd42da7baabe4e518eaf11c393596a9d | HTTP requests causing a high number of origin errors. |

Note

This rule is available for zones on any plan.

While Cloudflare's network is built to automatically monitor and mitigate large DDoS attacks, Cloudflare also helps mitigate smaller DDoS attacks, based on the following general rules:

* For zones on any plan, Cloudflare will apply mitigations when the HTTP error rate is above the _High_ (default) sensitivity level of 1,000 errors-per-second rate threshold. You can decrease the sensitivity level by configuring the HTTP DDoS Attack Protection managed ruleset.
* For zones on Pro, Business, and Enterprise plans, Cloudflare performs an additional check for better detection accuracy: the errors-per-second rate must also be at least five times the normal origin traffic levels before applying DDoS mitigations.

All HTTP errors in the `52x` range (Internal Server Error) and all errors in the `53x` range excluding [530](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-530) are considered when factoring in the error rate. For DDoS mitigations based on HTTP error rate, you cannot exclude specific HTTP error codes.

For more information on the types of DDoS attacks covered by Cloudflare's DDoS protection, refer to [DDoS attack coverage](https://developers.cloudflare.com/ddos-protection/about/attack-coverage/).

## Availability

The HTTP DDoS Attack Protection managed ruleset protects Cloudflare customers on all plans for zones [onboarded to Cloudflare](https://developers.cloudflare.com/dns/zone-setups/full-setup/). All customers can customize the ruleset both at the zone level and at the account level.

Customers on Enterprise plans with the Advanced DDoS Protection subscription can create up to 10 overrides (or up to 10 rules, for API users) with custom [expressions](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/override-expressions/), to customize the DDoS protection for different incoming requests.

Other customers can only create one override (or rule) and they cannot customize the rule expression. In this case, the single override, containing one or more configurations, will always apply to all incoming traffic.

## Related Cloudflare products

To block additional L7 attacks you can use other Cloudflare products like the [Cloudflare WAF](https://developers.cloudflare.com/waf/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/http/","name":"HTTP DDoS Attack Protection"}}]}
```

---

---
title: Overrides
description: Customize HTTP DDoS Attack Protection rule actions and sensitivity levels.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Overrides

When Cloudflare's DDoS Protection systems detect an attack, an ephemeral mitigation rule is created and installed in-line to mitigate the attack. A mitigation rule is generated based on the logic of the DDoS Protection managed ruleset. Each mitigation rule is generated from a single managed rule.

All mitigations and its associated managed rules are evaluated in order by the DDoS systems one by one. Cloudflare will go through all of the rule overrides defined in the ruleset overrides until one matches the managed rule, and apply the action and stop at that point. Otherwise, the evaluation will continue in order until a rule matches.

You can create only one ruleset override that can contain one or multiple rule overrides.

Note

Enterprise customers with the [Advanced DDoS Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/) add-on can create up to 10 ruleset overrides.

A rule override instructs the DDoS system on the action it should take against the attack according to its matching managed rule.

However, within a rule override, specificity matters and the DDoS system will choose the more specific configuration. A rule override takes precedence over the ruleset override.

## Example

A DDoS managed ruleset contains the following managed rules:

* **Managed rule 1**
* **Managed rule 2**
* **Managed rule 3**

The following ruleset overrides have been configured:

* **Ruleset override A**  
   * **Managed rule 1** is set to `block`
* **Ruleset override B**  
   * The action of the entire ruleset (or _all managed rules_) is set to `Managed Challenge`  
   * **Managed rule 1** is set to `log`  
   * **Managed rule 2** is set to `log`
* **Ruleset override C**  
   * **Managed rule 3** is set to `log`

### Use case

A DDoS attack was detected on **managed rules 1**, **2**, and **3**, and has generated a mitigation rule.

* Since **managed rule 1** matches **ruleset override A**, Cloudflare will `block` the attacks and not proceed with the rest of the rules.
* **Managed rule 2** does not match **ruleset override A**, so Cloudflare proceeds to **ruleset override B**.  
**Ruleset override B** matches both all managed rules and **managed rule 2**, but specificity takes precedence. It does not `challenge` and instead proceeds with `log` since it matches the most specific managed rule.
* **Managed rule 3** does not match **ruleset override A**, so Cloudflare proceeds to **rule override B**. Since **ruleset override B** sets _all managed rules_ to `challenge`, then Cloudflare does not proceed to **ruleset override C**.

An additional dimension to take into account is Cloudflare’s DDoS systems will apply a given rule override only if its conditions are met — which includes the Sensitivity level. So, while it needs to match and modify the correct managed rule (or everything in the case of all managed rules above), it also has to meet the specified Sensitivity level of the rule.

* **Rule override A**  
   * _All managed rules_ are set to `challenge` at low sensitivity
* **Rule override B**  
   * **Managed rule 1** is set to `log` at default sensitivity

You receive a small attack below the threshold for low sensitivity, but above the threshold for high sensitivity on **managed rule 1**.

* **Rule override A** does not meet the low sensitivity threshold. Therefore, we do not match the override and do not mitigate the attack, but proceed to evaluate the next managed rule in case the rule override instructs DoS to mitigate.
* **Rule override B** sets `log` at default visibility, which matches the condition. So, the defined action is applied and attack traffic is logged.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/http/","name":"HTTP DDoS Attack Protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/managed-rulesets/http/http-overrides/","name":"Overrides"}}]}
```

---

---
title: Configure via API
description: Create and manage HTTP DDoS Attack Protection overrides using the Cloudflare API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configure via API

Configure the HTTP DDoS Attack Protection managed ruleset by defining overrides using the [Rulesets API](https://developers.cloudflare.com/ruleset-engine/rulesets-api/).

Each zone has the HTTP DDoS Attack Protection managed ruleset enabled by default. This means that you do not need to deploy the managed ruleset to the `ddos_l7` phase ruleset explicitly. You only have to create a rule in the phase ruleset to deploy the managed ruleset if you need to configure overrides.

If you are using Terraform, refer to [DDoS managed rulesets configuration using Terraform](https://developers.cloudflare.com/terraform/additional-configurations/ddos-managed-rulesets/#example-configure-http-ddos-attack-protection).

## Configure an override for the HTTP DDoS Attack Protection managed ruleset

Use overrides to configure the HTTP DDoS Attack Protection managed ruleset. Overrides allow you to define a different action or sensitivity level from the default values. For more information on the available action and sensitivity level values, refer to [Ruleset parameters](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/override-parameters/).

Overrides can have a ruleset, tag, or rule scope. Tag and rule configurations have greater priority than ruleset configurations.

You can create overrides at the zone level and at the account level. Account-level overrides allow you to apply the same override to several zones in your account with a single rule. For example, you can use an account-level override to lower the sensitivity of a specific managed ruleset rule or exclude an [IP list](https://developers.cloudflare.com/waf/tools/lists/custom-lists/#ip-lists) for multiple zones. However, if a given zone has overrides for the HTTP DDoS Attack Protection managed ruleset, the account-level overrides will not be evaluated for that zone.

Important

* The HTTP DDoS Attack Protection managed ruleset is always enabled — you cannot disable its rules using an override with `"enabled": false`.
* The managed ruleset includes some read-only rules that you cannot override.
* If you configure both account-level and zone-level overrides, only the zone-level overrides (the most specific ones) will be evaluated.
* Currently, account-level overrides for the HTTP DDoS Attack Protection managed ruleset are only available via API.

### Creating multiple rules

Note

Only available to Enterprise customers with the Advanced DDoS Protection subscription, which can create up to 10 rules.

Create multiple rules in the `ddos_l7` phase entry point ruleset to define different overrides for different sets of incoming requests. Set each rule expression according to the traffic whose HTTP DDoS protection you wish to customize.

Rules in the phase entry point ruleset, where you create overrides, are evaluated in order until there is a match for a rule expression and sensitivity level, and Cloudflare will apply the first rule that matches the request. Therefore, the rule order in the entry point ruleset is very important.

## Example API calls

### Zone-level configuration example

The following `PUT` example creates a new phase ruleset (or updates the existing one) for the `ddos_l7` phase at the zone level. The request includes several overrides to adjust the default behavior of the HTTP DDoS Attack Protection managed ruleset. These overrides are the following:

* All rules of the managed ruleset will use the `managed_challenge` action and have a sensitivity level of `medium`.
* All rules tagged with `<TAG_NAME>` will have a sensitivity level of `low`.
* The rule with ID `<MANAGED_RULESET_RULE_ID>` will use the `block` action.

Request

```

curl --request PUT \

https://api.cloudflare.com/client/v4/zones/{zone_id}/rulesets/phases/ddos_l7/entrypoint \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "description": "Execute HTTP DDoS Attack Protection managed ruleset in the zone-level phase entry point ruleset",

  "rules": [

    {

      "action": "execute",

      "action_parameters": {

        "id": "<MANAGED_RULESET_ID>",

        "overrides": {

          "sensitivity_level": "medium",

          "action": "managed_challenge",

          "categories": [

            {

              "category": "<TAG_NAME>",

              "sensitivity_level": "low"

            }

          ],

          "rules": [

            {

              "id": "<MANAGED_RULESET_RULE_ID>",

              "action": "block"

            }

          ]

        }

      },

      "expression": "true"

    }

  ]

}'


```

The response returns the created (or updated) phase entry point ruleset.

Response

```

{

  "result": {

    "id": "<PHASE_ENTRY_POINT_RULESET_ID>",

    "name": "default",

    "description": "Execute HTTP DDoS Attack Protection managed ruleset in the zone-level phase entry point ruleset",

    "kind": "zone",

    "version": "1",

    "rules": [

      {

        "id": "<RULE_ID>",

        "version": "1",

        "action": "execute",

        "action_parameters": {

          "id": "<MANAGED_RULESET_ID>",

          "version": "latest",

          "overrides": {

            "action": "managed_challenge",

            "categories": [

              {

                "category": "<TAG_NAME>",

                "sensitivity_level": "low"

              }

            ],

            "rules": [

              {

                "id": "<MANAGED_RULESET_RULE_ID>",

                "action": "block"

              }

            ],

            "sensitivity_level": "medium"

          }

        },

        "expression": "true",

        "last_updated": "2021-06-16T04:14:47.977741Z",

        "ref": "<RULE_REF>",

        "enabled": true

      }

    ],

    "last_updated": "2021-06-16T04:14:47.977741Z",

    "phase": "ddos_l7"

  }

}


```

For more information on defining overrides for managed rulesets using the Rulesets API, refer to [Override a managed ruleset](https://developers.cloudflare.com/ruleset-engine/managed-rulesets/override-managed-ruleset/) in the Ruleset Engine documentation.

### Account-level configuration example

The following `PUT` example creates a new phase ruleset (or updates the existing one) for the `ddos_l7` phase at the account level. The example defines a single rule override for requests coming from IP addresses in the `allowlisted_ips` [IP list](https://developers.cloudflare.com/waf/tools/lists/custom-lists/#ip-lists), with the following configuration:

* The rule with ID `<MANAGED_RULESET_RULE_ID>`, belonging to the HTTP DDoS Attack Protection managed ruleset (with ID `<MANAGED_RULESET_ID>`), will have an `eoff` (_Essentially Off_) sensitivity level and it will perform a `log` action.

Note

Custom rule expressions (different from `"true"`) and the `log` action require an Enterprise plan with the Advanced DDoS Protection subscription.

Request

```

curl --request PUT \

https://api.cloudflare.com/client/v4/accounts/{account_id}/rulesets/phases/ddos_l7/entrypoint \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "description": "Disable a managed ruleset rule for allowlisted IP addresses",

  "rules": [

    {

      "expression": "ip.src in $allowlisted_ips",

      "action": "execute",

      "action_parameters": {

        "id": "<MANAGED_RULESET_ID>",

        "overrides": {

          "rules": [

            {

              "id": "<MANAGED_RULESET_RULE_ID>",

              "action": "log",

              "sensitivity_level": "eoff"

            }

          ]

        }

      }

    }

  ]

}'


```

The response returns the created (or updated) phase entry point ruleset.

Response

```

{

  "result": {

    "id": "<PHASE_ENTRY_POINT_RULESET_ID>",

    "name": "default",

    "description": "Disable a managed ruleset rule for allowlisted IP addresses",

    "kind": "root",

    "version": "1",

    "rules": [

      {

        "id": "<RULE_ID>",

        "version": "1",

        "action": "execute",

        "action_parameters": {

          "id": "<MANAGED_RULESET_ID>",

          "version": "latest",

          "overrides": {

            "rules": [

              {

                "id": "<MANAGED_RULESET_RULE_ID>",

                "action": "log",

                "sensitivity_level": "eoff"

              }

            ]

          }

        },

        "expression": "ip.src in $allowlisted_ips",

        "last_updated": "2022-10-16T04:14:47.977741Z",

        "ref": "<RULE_REF>",

        "enabled": true

      }

    ],

    "last_updated": "2022-10-16T04:14:47.977741Z",

    "phase": "ddos_l7"

  }

}


```

For more information on defining overrides for managed rulesets using the Rulesets API, refer to [Override a managed ruleset](https://developers.cloudflare.com/ruleset-engine/managed-rulesets/override-managed-ruleset/) in the Ruleset Engine documentation.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/http/","name":"HTTP DDoS Attack Protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/managed-rulesets/http/http-overrides/","name":"Overrides"}},{"@type":"ListItem","position":6,"item":{"@id":"/ddos-protection/managed-rulesets/http/http-overrides/configure-api/","name":"Configure via API"}}]}
```

---

---
title: Configure in the dashboard
description: Create HTTP DDoS Attack Protection overrides in the Cloudflare dashboard.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configure in the dashboard

Configure the HTTP DDoS Attack Protection managed ruleset by defining [overrides](https://developers.cloudflare.com/ruleset-engine/managed-rulesets/override-managed-ruleset/) in the Cloudflare dashboard. DDoS overrides allow you to customize the **action** and **sensitivity** of one or more rules in the managed ruleset.

For more information on the available parameters and allowed values, refer to [Ruleset parameters](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/override-parameters/).

Number of available overrides

If you are an Enterprise customer with the Advanced DDoS Protection subscription, you can define up to 10 overrides. These overrides can have a custom expression so that the override only applies to a subset of incoming requests. If you do not have the Advanced DDoS Protection subscription, you can only deploy one override which will always apply to all incoming requests.

If you cannot deploy any additional overrides, consider editing an existing override to adjust rule configuration.

Create multiple rules in the `ddos_l7` phase entry point ruleset to define different overrides for different sets of incoming requests. Set each rule expression according to the traffic whose HTTP DDoS protection you wish to customize.

Rules in the phase entry point ruleset, where you create overrides, are evaluated in order until there is a match for a rule expression and sensitivity level, and Cloudflare will apply the first rule that matches the request. Therefore, the rule order in the entry point ruleset is very important.

## Access

* [  New dashboard ](#tab-panel-7909)
* [ Old dashboard ](#tab-panel-7910)

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. Go to the **DDoS protection** tab.
3. On **HTTP DDoS attack protection**, select **Create override**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and website.
2. Go to **Security** \> **DDoS**.
3. Next to **HTTP DDoS attack protection**, select **Deploy a DDoS override**.

### Create a DDoS override

1. Enter a descriptive name for the override in **Override name**.
2. If you are an Enterprise customer with the Advanced DDoS Protection subscription:  
   1. Under **Override scope**, review the scope of the override — by default, all incoming requests for the current zone.  
   2. If necessary, select **Edit scope** and configure the [custom filter expression](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/override-expressions/) that will determine the override scope.
3. Depending on what you wish to override, refer to the following sections (you can perform both configurations on the same override):  
Configure all the rules in the ruleset (ruleset override)  
   1. To always apply a given action for all the rules in the ruleset, select an action in **Ruleset action**.  
   2. To set the sensitivity level for all the rules in the ruleset, select a value in **Ruleset sensitivity**.  
Configure one or more rules  
   1. Under **Rule configuration**, select **Browse rules**.  
   2. Search for the rules you wish to configure using the available filters. You can search by [tag](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/rule-categories/) (also known as category).  
   3. To configure a single rule, select the desired value for a field in the displayed dropdowns next to the rule.  
   To configure more than one rule, select the rules using the row checkboxes and update the fields for the selected rules using the dropdowns displayed before the table. You can also configure all the rules with a given tag. For more information, refer to [Configure a managed ruleset](https://developers.cloudflare.com/waf/managed-rules/deploy-zone-dashboard/#configure-a-managed-ruleset).  
   4. Select **Next**.  
Notes  
   * Tag and rule overrides have priority over ruleset overrides.  
   * The managed ruleset includes some read-only rules that you cannot override.
4. Select **Save**.

### Delete a DDoS override

* [  New dashboard ](#tab-panel-7911)
* [ Old dashboard ](#tab-panel-7912)

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. Go to the **DDoS protection** tab.
3. Select the override.
4. Select **Delete deployment**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Security > DDoS**.
3. Next to the DDoS override you wish to delete, select **Delete**.
4. Select **Delete** to confirm the operation.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/http/","name":"HTTP DDoS Attack Protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/managed-rulesets/http/http-overrides/","name":"Overrides"}},{"@type":"ListItem","position":6,"item":{"@id":"/ddos-protection/managed-rulesets/http/http-overrides/configure-dashboard/","name":"Configure in the dashboard"}}]}
```

---

---
title: Override examples
description: Example override configurations for HTTP DDoS Attack Protection rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Override examples

## Use cases

The following scenarios detail how you can make use of override rules as a solution to common HTTP DDoS Protection issues.

### Traffic from your mobile application is blocked by a DDoS Managed Rule

The traffic from your mobile application may have appeared suspicious, causing a DDoS Managed Rule to block it.

You should identify the Managed Rule blocking the traffic and change the sensitivity level to `Medium`. If traffic continues to be blocked by the managed rule, set the sensitivity level to `Low` or `Essentially off`.

If you have access to filter expressions, you can create an override to target the specific affected traffic.

### Traffic is flagged by an adaptive rule based on the location and may be an attack

If you recognize that the traffic flagged by an adaptive rule may be considered an attack, you can create an override rule to enable the adaptive rule in mitigation mode to `challenge` (if it is browser traffic) or `block` (for other suspicious traffic).

### Legitimate traffic is incorrectly identified as an attack and causes a false positive

A false positive is an incorrect identification. In the case of DDoS protection, there is a false positive when legitimate traffic is mistakenly classified as attack traffic. This can occur when legacy applications, Internet services, or faulty client applications generate legitimate traffic that appears suspicious, has odd traffic patterns, deviates from best practices, or violates protocols.

In these cases, Cloudflare's DDoS Protection systems may flag that traffic as malicious and apply mitigation actions. If the traffic is in fact legitimate and not part of an attack, the mitigation actions can cause service disruptions and outages to your Internet properties.

To remedy a false positive:

* [  New dashboard ](#tab-panel-7913)
* [ Old dashboard ](#tab-panel-7914)

1. In the Cloudflare dashboard, go to the [Network analytics ↗](https://dash.cloudflare.com/?to=/:account/networking-insights/analytics/network-analytics/transport-analytics) page.
2. Apply filters to the displayed data.  
For WAF/CDN customers  
   1. Select the zone that is experiencing DDoS attack false positives.  
   2. Go to **Security** \> **Analytics** \> **Events** tab.  
   3. Select **Add filter** and filter by `Service equals HTTP DDoS`.  
For Magic Transit and Spectrum customers  
   1. Go to Account Home > **Analytics & Logs** \> **Network Analytics**.  
   2. Identify the legitimate traffic that is causing the false positives. Use the Attack ID number included in the DDoS alert (if you received one), or apply dashboard filters such as destination IP address and port.
3. Scroll down to **Top events by source** \> **HTTP DDoS rules**.
4. Copy the rule name.
5. Go to your zone > **Security** \> **Security rules** \> **DDoS protection** tab and select **Create override**. If you cannot deploy any additional overrides, edit an existing override to adjust rule configuration.
6. Select **Browse rules** and paste the rule name in the search field.
7. Decrease the rule's **Sensitivity Level** to _Essentially Off_ or change the rule action to _Log_ (if supported by your current plan and subscriptions).
8. Select **Next** and then select **Save**.

1. In the Cloudflare dashboard, go to the [Network analytics ↗](https://dash.cloudflare.com/?to=/:account/networking-insights/analytics/network-analytics/transport-analytics) page.
2. Apply filters to the displayed data.  
For WAF/CDN customers  
   1. Select the zone that is experiencing DDoS attack false positives.  
   2. Go to **Security** \> **Events**.  
   3. Select **Add filter** and filter by `Service equals HTTP DDoS`.  
For Magic Transit and Spectrum customers  
   1. Go to Account Home > **Analytics & Logs** \> **Network Analytics**.  
   2. Identify the legitimate traffic that is causing the false positives. Use the Attack ID number included in the DDoS alert (if you received one), or apply dashboard filters such as destination IP address and port.
3. Scroll down to **Top events by source** \> **HTTP DDoS rules**.
4. Copy the rule name.
5. Go to your zone > **Security** \> **DDoS** and select **Deploy a DDoS override**. If you cannot deploy any additional overrides, edit an existing override to adjust rule configuration.
6. Select **Browse rules** and paste the rule name in the search field.
7. Decrease the rule's **Sensitivity Level** to _Essentially Off_ or change the rule action to _Log_ (if supported by your current plan and subscriptions).
8. Select **Next** and then select **Save**.

Once saved, the rule takes effect within one or two minutes. The rule adjustment should provide immediate remedy, which you can view in the [analytics dashboard](https://developers.cloudflare.com/ddos-protection/reference/analytics/).

#### Update the adjusted rules later

Later, you can change the [sensitivity level](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/override-parameters/#sensitivity-level) of the rule causing the false positives to avoid future issues, and change the rule action back to its default value.

Recommendation: Enable DDoS alerts

Cloudflare recommends that you create notifications for [DDoS alerts](https://developers.cloudflare.com/ddos-protection/reference/alerts/) to get real-time notifications on detected and mitigated attacks automatically performed by Cloudflare's systems. When you receive these notifications, you can review if it is in fact a real DDoS attack, or if it is a false positive, and then take action to remedy it.

#### Avoid false positives while retaining protection and visibility

To see what DDoS Managed Rules do in a high sensitivity level while remaining protected by blocking attacks at a low sensitivity level, Advanced DDoS protection customers can [create a first override](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/configure-dashboard/#create-a-ddos-override) that blocks attacks at a low sensitivity and a second override to log at a high sensitivity.

The overrides must be set in that order. Otherwise, it will not work. This is because overrides are evaluated in order and will stop at the first override that matches both expression and sensitivity. Setting the overrides in the wrong order would cause the `Log` override at a high sensitivity to match all instances. As a result, Cloudflare will never evaluate the `Block` override that would be placed behind it, causing all rules to be set in `Log` mode.

If an override without an expression matches, Cloudflare will not evaluate the expressions that follow it.

### An attack is incorrectly identified as legitimate traffic and causes a false negative

A false negative is a lack of identification. In the case of DDoS protection, there is a false negative when attack traffic is mistakenly classified as legitimate traffic and is not mitigated. This can occur when the attack traffic is not sufficiently high to trigger mitigation actions or if there are no rules matching the attack.

To address a false negative:

* If you are a WAF/CDN customer, follow the steps in the [Proactive DDoS defense](https://developers.cloudflare.com/ddos-protection/best-practices/proactive-defense/) page, which guides you on enabling the _Under Attack_ mode and creating rate limiting rules and WAF custom rules as needed.
* If you are a Magic Transit customer, [use Cloudflare Network Firewall rules](https://developers.cloudflare.com/cloudflare-one/traffic-policies/packet-filtering/add-policies/) to help mitigate the attack.

### Incomplete mitigations

An incomplete mitigation is a case when the DDoS protection systems have applied mitigation, but not all the attack was mitigated. This can happen when Cloudflare's systems apply a mitigation action that is less strict than what the attack requires.

The system chooses the mitigation action based on the logic and the DDoS protection system's confidence that the traffic is indeed part of an attack:

* For high-confidence rules, the system will apply a strict mitigation action such as the _Block_ action.
* For low-confidence rules, the system will apply a less strict mitigation rule such as _Challenge_ or _Force Connection Close_.

If you are experiencing a DDoS attack detected by Cloudflare and the applied mitigation action is not sufficiently strict, change the rule action to _Block_:

* [  New dashboard ](#tab-panel-7915)
* [ Old dashboard ](#tab-panel-7916)

1. In the Cloudflare dashboard, go to the [Network analytics ↗](https://dash.cloudflare.com/?to=/:account/networking-insights/analytics/network-analytics/transport-analytics) page.
2. Apply filters to the displayed data.  
For WAF/CDN customers  
   1. Select the zone that is experiencing an incomplete mitigation of a DDoS attack.  
   2. Go to **Security** \> **Analytics** \> **Events** tab.  
   3. Select **Add filter** and filter by `Service equals HTTP DDoS`.  
For Magic Transit and Spectrum customers  
   1. Go to Account Home > **Analytics & Logs** \> **Network Analytics**.  
   2. Identify the DDoS attack that is having incomplete mitigations. Use the Attack ID number included in the DDoS alert (if you received one), or apply dashboard filters such as destination IP address and port.
3. Scroll down to **Top events by source** \> **HTTP DDoS rules**.
4. Copy the rule name.
5. Go to your zone > **Security** \> **Security rules** \> **DDoS protection** tab and select **Create override**. If you cannot deploy any additional overrides, edit an existing override to adjust rule configuration.
6. Select **Browse rules** and paste the rule name in the search field.
7. Change the rule's **Action** to _Block_.
8. Select **Next** and then select **Save**.

1. In the Cloudflare dashboard, go to the [Network analytics ↗](https://dash.cloudflare.com/?to=/:account/networking-insights/analytics/network-analytics/transport-analytics) page.
2. Apply filters to the displayed data.  
For WAF/CDN customers  
   1. Select the zone that is experiencing an incomplete mitigation of a DDoS attack.  
   2. Go to **Security** \> **Events**.  
   3. Select **Add filter** and filter by `Service equals HTTP DDoS`.  
For Magic Transit and Spectrum customers  
   1. Go to Account Home > **Analytics & Logs** \> **Network Analytics**.  
   2. Identify the DDoS attack that is having incomplete mitigations. Use the Attack ID number included in the DDoS alert (if you received one), or apply dashboard filters such as destination IP address and port.
3. Scroll down to **Top events by source** \> **HTTP DDoS rules**.
4. Copy the rule name.
5. Go to your zone > **Security** \> **DDoS** and select **Deploy a DDoS override**. If you cannot deploy any additional overrides, edit an existing override to adjust rule configuration.
6. Select **Browse rules** and paste the rule name in the search field.
7. Change the rule's **Action** to _Block_.
8. Select **Next** and then select **Save**.

Once saved, the rule takes effect within one or two minutes. The rule adjustment should provide immediate remedy, which you can view in the [analytics dashboard](https://developers.cloudflare.com/ddos-protection/reference/analytics/).

#### Alternate procedure

If you cannot stop an attack from overloading your origin web server using the above steps, [contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) for assistance, providing the following details:

* Time period of the attack (UTC timestamp)
* Domain/path being targeted (zone name/ID)
* Attack frequency
* Steps to reproduce the issue, with actual results versus expected results
* Any relevant additional information such as site URLs, error messages, screenshots, or relevant logs from your origin web server

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/http/","name":"HTTP DDoS Attack Protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/managed-rulesets/http/http-overrides/","name":"Overrides"}},{"@type":"ListItem","position":6,"item":{"@id":"/ddos-protection/managed-rulesets/http/http-overrides/override-examples/","name":"Override examples"}}]}
```

---

---
title: Override expressions
description: Expression fields and operators for scoping HTTP DDoS Attack Protection overrides.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Override expressions

Note

Only available to Enterprise customers with the Advanced DDoS Protection subscription.

Set an override expression for the HTTP DDoS Attack Protection managed ruleset to define a specific scope for [sensitivity level](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/override-parameters/#sensitivity-level) or [action](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/override-parameters/#action) adjustments.

For example, you can set different sensitivity levels for different request URI paths: a medium sensitivity level for URI path `A` and a low sensitivity level for URI path `B`.

## Available expression fields

You can use the following fields in override expressions:

* `cf.bot_management.ja3_hash`
* `cf.bot_management.ja4`
* `cf.client.bot`
* `cf.tls_cipher`
* `cf.tls_client_auth.cert_verified`
* `cf.tls_version`
* `cf.verified_bot_category`
* `http.cookie`
* `http.host`
* `http.referer`
* `http.request.headers`
* `http.request.headers.names`
* `http.request.headers.truncated`
* `http.request.headers.values`
* `http.request.uri`
* `http.request.uri.path`
* `http.request.uri.path.extension`
* `http.request.uri.query`
* `http.request.full_uri`
* `http.request.method`
* `http.request.version`
* `http.request.cookies`
* `http.user_agent`
* `http.x_forwarded_for`
* `ip.src`
* `ip.src.asnum`
* `ip.src.continent`
* `ip.src.country`
* `ip.src.is_in_european_union`
* `ssl`

Refer to the [Fields reference](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/) in the Rules language documentation for more information.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/http/","name":"HTTP DDoS Attack Protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/managed-rulesets/http/http-overrides/","name":"Overrides"}},{"@type":"ListItem","position":6,"item":{"@id":"/ddos-protection/managed-rulesets/http/http-overrides/override-expressions/","name":"Override expressions"}}]}
```

---

---
title: Parameters
description: Configurable parameters for HTTP DDoS Attack Protection rule overrides.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Parameters

Configure the HTTP DDoS Attack Protection managed ruleset to change the action applied to a given attack or modify the sensitivity level of the detection mechanism. You can [configure the managed ruleset in the Cloudflare dashboard](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/configure-dashboard/) or [define overrides via Rulesets API](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/configure-api/).

The available parameters are the following:

* [Action](#action)
* [Sensitivity Level](#sensitivity-level)

## Action

API property name: `"action"`.

The action that will be performed for requests that match specific rules of Cloudflare's DDoS mitigation services. The available actions are:

* **Block**  
   * API value: `"block"`.  
   * Blocks HTTP requests that match the rule expression.
* **Managed Challenge**  
   * API value: `"managed_challenge"`.  
   * [Managed Challenges](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/#managed-challenge) help reduce the lifetimes of human time spent solving CAPTCHAs across the Internet. Depending on the characteristics of a request, Cloudflare will dynamically choose the appropriate type of challenge based on specific criteria.
* **Interactive Challenge**  
   * API value: `"challenge"`.  
   * Presents an interactive challenge to the clients making HTTP requests that match a rule expression.
* **Log**  
   * API value: `"log"`.  
   * Only available on Enterprise plans with the Advanced DDoS Protection subscription. Logs requests that match the expression of a rule detecting HTTP DDoS attacks. Recommended for validating a rule before committing to a more severe action.
* **Connection Close**  
   * API value: _N/A_ (internal rule action that you cannot use in overrides).  
   * The client is instructed to establish a new connection (by disabling `keep-alive`) instead of reusing the existing connection. Existing requests are not affected.
* **Force Connection Close**  
   * API value: _N/A_ (internal rule action that you cannot use in overrides).  
   * Closes ongoing HTTP connections. This action does not block a request, but it forces the client to reconnect. For HTTP/2 and HTTP/3 connections, the connection will be closed even if it breaks other requests running on the same connection.  
   * The performed action depends on the HTTP version:  
         * HTTP/1: set the [Connection header ↗](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Connection#directives) to `close`.  
         * HTTP/2: send a [GOAWAY frame ↗](https://datatracker.ietf.org/doc/html/rfc7540#section-6.8) to the client.
* **DDoS Dynamic**  
   * API value: _N/A_ (internal rule action that you cannot use in overrides).  
   * Performs a specific action according to a set of internal guidelines defined by Cloudflare. The executed action can be one of the above or an undisclosed mitigation action.

## Sensitivity Level

API property name: `"sensitivity_level"`.

Defines how sensitive a rule is. Affects the thresholds used to determine if an attack should be mitigated. A higher sensitivity level means having a lower threshold, while a lower sensitivity level means having a higher threshold.

The available sensitivity levels are:

| UI value          | API value |
| ----------------- | --------- |
| _High_            | "default" |
| _Medium_          | "medium"  |
| _Low_             | "low"     |
| _Essentially Off_ | "eoff"    |

The default sensitivity level is _High_.

In most cases, when you select the _Essentially Off_ sensitivity level the rule will not trigger for any of the selected actions, including _Log_. However, if the attack is extremely large, Cloudflare's protection systems will still trigger the rule's mitigation action to protect Cloudflare's network.

_Essentially Off_ means that we have set an exceptionally low sensitivity level so in most cases traffic will not be mitigated for you. However, attack traffic will be mitigated at exceptional levels to ensure the safety and stability of the Cloudflare network.

**Log** means that requests will not be mitigated but only logged and shown on the dashboard. However, attack traffic will be mitigated at exceptional levels to ensure the safety and stability of the Cloudflare network.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/http/","name":"HTTP DDoS Attack Protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/managed-rulesets/http/override-parameters/","name":"Parameters"}}]}
```

---

---
title: Rule categories
description: Categories of rules in the HTTP DDoS Attack Protection managed ruleset.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Rule categories

The main categories (or tags) of HTTP DDoS Attack Protection managed rules are the following:

| Name             | Description                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| botnets          | Rules for requests from known botnets, with very high accuracy and low risk of false positives. It is recommended that you keep these rules enabled.                                                                                                                                                                                                                                                                                         |
| unusual-requests | Rules for requests with suspicious characteristics that are not usually seen in legitimate traffic.                                                                                                                                                                                                                                                                                                                                          |
| advanced         | Rules related to features available to Advanced DDoS Protection customers, such as [Adaptive DDoS Protection](https://developers.cloudflare.com/ddos-protection/managed-rulesets/adaptive-protection/).                                                                                                                                                                                                                                      |
| generic          | Rules for detecting and mitigating floods of requests. These rules are useful for mitigating attacks that have no known signatures, but they may also trigger on unusually high volumes of legitimate traffic. To reduce the risk of false positives, their request per second (rps) activation threshold is higher. These rules either rate-limit or challenge traffic by default, but you can override them to block traffic if necessary. |
| read-only        | Highly targeted rules for mitigating DDoS attacks with a high confidence rate. These rules are read-only — you cannot override their sensitivity level or action.                                                                                                                                                                                                                                                                            |
| test             | Rules used for testing the detection, mitigation, and alerting capabilities of Cloudflare's DDoS protection products.                                                                                                                                                                                                                                                                                                                        |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/http/","name":"HTTP DDoS Attack Protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/managed-rulesets/http/rule-categories/","name":"Rule categories"}}]}
```

---

---
title: Network-layer DDoS Attack Protection
description: Pre-configured rules that detect and mitigate DDoS attacks at layers 3 and 4.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Network-layer DDoS Attack Protection

The Cloudflare Network-layer [DDoS Attack ↗](https://www.cloudflare.com/en-gb/learning/ddos/what-is-a-ddos-attack/) Protection managed ruleset is a set of pre-configured rules used to match [known DDoS attack vectors](https://developers.cloudflare.com/ddos-protection/about/attack-coverage/) at levels 3 and 4 of the OSI model.

Cloudflare updates the list of rules in the managed ruleset on a regular basis. Refer to the [changelog](https://developers.cloudflare.com/ddos-protection/change-log/network/) for more information on recent and upcoming changes.

The Network-layer DDoS Attack Protection managed ruleset is always enabled — you can only customize its behavior.

## Ruleset configuration

You may need to adjust the behavior of specific rules in case of false positives or due to specific traffic patterns.

Adjust the behavior of the rules in the managed ruleset by modifying the following parameters:

* The performed **action** when an attack is detected
* The **sensitivity level** of attack detection mechanisms

To adjust rule behavior, use one of the following methods:

* [Configure the managed ruleset in the Cloudflare dashboard](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/configure-dashboard/).
* [Configure the managed ruleset via Cloudflare API](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/configure-api/).
* [Configure the managed ruleset using Terraform](https://developers.cloudflare.com/terraform/additional-configurations/ddos-managed-rulesets/#example-configure-network-layer-ddos-attack-protection).

You can only configure the behavior of the managed ruleset to set a stronger or weaker mitigation action (depending on the default action of a specific rule, you can change it to `Block` if the default action is `DDoS Dynamic` or `Log`.), or a lower default sensitivity for all rules. Refer to [Managed ruleset parameters](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/override-parameters/) for more information.

Overrides can apply to all packets or to a subset of incoming packets, depending on the override expression. Refer to [Override expressions](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/override-expressions/) for more information.

### Network Analytics rule display

Cloudflare regularly deploys new detection rules to the Network-layer DDoS managed ruleset. To ensure high accuracy and minimize false positives, these rules undergo a testing phase before they are fully promoted.

When a rule is in its testing phase, you may notice specific behaviors in the Cloudflare dashboard.

New rules often default to `Log` (visible in **DDoS Managed Rules** \> **Browse Rules**). This allows Cloudflare to evaluate the rule's performance against real-world traffic without impacting legitimate packets.

In the [Network Analytics](https://developers.cloudflare.com/analytics/network-analytics/) dashboard, traffic matched by these testing-phase rules is labeled as `Log (rule disabled)`. This is a reporting convention indicating the rule is in a pre-production monitoring state.

While you can manually override a rule from `Log` to `Block`, consider the following before doing so:

* Rules in the testing phase have not yet been fully tuned for broad deployment. Overriding them to a mitigation action (like `Block`) may increase the risk of dropping legitimate traffic.
* The default action of a rule is decided during the testing period. Cloudflare may set its default action to **DDoS Dynamic**, which may use rate-limiting or a multi-step mitigation combination based on traffic factors. By applying a manual `Block` override, you prevent your configuration from automatically inheriting the more nuanced DDoS Dynamic action once it is released.

If you choose to override a testing rule to mitigate an active attack, Cloudflare recommends reviewing that override periodically to see if the rule has been promoted to a permanent default action.

## Availability

The Network-layer DDoS Attack Protection managed ruleset is available in all Cloudflare plans for:

* Zones [onboarded to Cloudflare](https://developers.cloudflare.com/dns/zone-setups/full-setup/) (zones with their traffic routed through the Cloudflare network)
* IP applications onboarded to [Spectrum](https://developers.cloudflare.com/spectrum/)
* IP prefixes onboarded to [Magic Transit](https://developers.cloudflare.com/magic-transit/)

However, only Magic Transit and Spectrum customers on an Enterprise plan can customize the managed ruleset.

## Related Cloudflare products

Magic Transit customers can configure the following additional products:

* Enable [Advanced TCP Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/) to detect and mitigate sophisticated out-of-state TCP attacks such as randomized and spoofed ACK floods or SYN and SYN-ACK floods.
* Create custom [Network Firewall](https://developers.cloudflare.com/cloudflare-network-firewall/) rules to block additional network-layer attacks.

Spectrum customers can use [IP Access](https://developers.cloudflare.com/waf/tools/ip-access-rules/) rules to block additional network-layer attacks.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/network/","name":"Network-layer DDoS Attack Protection"}}]}
```

---

---
title: Overrides
description: Customize Network-layer DDoS Attack Protection rule actions and sensitivity levels.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Overrides

When Cloudflare's DDoS Protection systems detect an attack, an ephemeral mitigation rule is created and installed in-line to mitigate the attack. A mitigation rule is generated based on the logic of the DDoS Protection managed ruleset. Each mitigation rule is generated from a single managed rule.

All mitigations and its associated managed rules are evaluated in order by the DDoS systems one by one. Cloudflare will go through all of the rule overrides defined in the ruleset overrides until one matches the managed rule, and apply the action and stop at that point. Otherwise, the evaluation will continue in order until a rule matches.

You can create only one ruleset override that can contain one or multiple rule overrides.

Note

Enterprise customers with the [Advanced DDoS Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/) add-on can create up to 10 ruleset overrides.

A rule override instructs the DDoS system on the action it should take against the attack according to its matching managed rule.

However, within a rule override, specificity matters and the DDoS system will choose the more specific configuration. A rule override takes precedence over the ruleset override.

## Example

A DDoS managed ruleset contains the following managed rules:

* **Managed rule 1**
* **Managed rule 2**
* **Managed rule 3**

The following ruleset overrides have been configured:

* **Ruleset override A**  
   * **Managed rule 1** is set to `block`
* **Ruleset override B**  
   * The action of the entire ruleset (or _all managed rules_) is set to `Managed Challenge`  
   * **Managed rule 1** is set to `log`  
   * **Managed rule 2** is set to `log`
* **Ruleset override C**  
   * **Managed rule 3** is set to `log`

### Use case

A DDoS attack was detected on **managed rules 1**, **2**, and **3**, and has generated a mitigation rule.

* Since **managed rule 1** matches **ruleset override A**, Cloudflare will `block` the attacks and not proceed with the rest of the rules.
* **Managed rule 2** does not match **ruleset override A**, so Cloudflare proceeds to **ruleset override B**.  
**Ruleset override B** matches both all managed rules and **managed rule 2**, but specificity takes precedence. It does not `challenge` and instead proceeds with `log` since it matches the most specific managed rule.
* **Managed rule 3** does not match **ruleset override A**, so Cloudflare proceeds to **rule override B**. Since **ruleset override B** sets _all managed rules_ to `challenge`, then Cloudflare does not proceed to **ruleset override C**.

An additional dimension to take into account is Cloudflare’s DDoS systems will apply a given rule override only if its conditions are met — which includes the Sensitivity level. So, while it needs to match and modify the correct managed rule (or everything in the case of all managed rules above), it also has to meet the specified Sensitivity level of the rule.

* **Rule override A**  
   * _All managed rules_ are set to `challenge` at low sensitivity
* **Rule override B**  
   * **Managed rule 1** is set to `log` at default sensitivity

You receive a small attack below the threshold for low sensitivity, but above the threshold for high sensitivity on **managed rule 1**.

* **Rule override A** does not meet the low sensitivity threshold. Therefore, we do not match the override and do not mitigate the attack, but proceed to evaluate the next managed rule in case the rule override instructs DoS to mitigate.
* **Rule override B** sets `log` at default visibility, which matches the condition. So, the defined action is applied and attack traffic is logged.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/network/","name":"Network-layer DDoS Attack Protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/managed-rulesets/network/network-overrides/","name":"Overrides"}}]}
```

---

---
title: Configure via API
description: Create and manage Network-layer DDoS Attack Protection overrides using the API.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configure via API

Configure the Cloudflare Network-layer DDoS Attack Protection managed ruleset by defining overrides at the account level using the [Rulesets API](https://developers.cloudflare.com/ruleset-engine/rulesets-api/).

Each account has the Network-layer DDoS Attack Protection managed ruleset enabled by default. This means that you do not need to deploy the managed ruleset to the `ddos_l4` phase entry point ruleset explicitly. You only have to create a rule in the phase entry point to deploy the managed ruleset if you need to configure overrides.

If you are using Terraform, refer to [DDoS managed rulesets configuration using Terraform](https://developers.cloudflare.com/terraform/additional-configurations/ddos-managed-rulesets/#example-configure-network-layer-ddos-attack-protection).

## Configure an override for the Network-layer DDoS Attack Protection managed ruleset

You can define overrides at the ruleset, tag, and rule level for all managed rulesets.

When configuring the Network-layer DDoS Attack Protection managed ruleset, use overrides to define a different **action** or **sensitivity** from the default values. For more information on these rule parameters and the allowed values, refer to [Managed ruleset parameters](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/override-parameters/).

Important

* The Network-layer DDoS Attack Protection managed ruleset is always enabled. You cannot disable its rules using an override with `"enabled": false`.
* The managed ruleset includes some read-only rules that you cannot override.
* You can only define overrides for the Network-layer DDoS Attack Protection managed ruleset at the account level.

## Example

The following `PUT` example creates a new phase ruleset (or updates the existing one) for the `ddos_l4` phase at the account level. The request includes several overrides to adjust the default behavior of the Network-layer DDoS Attack Protection managed ruleset. These overrides are the following:

* All rules of the Network-layer DDoS Attack Protection managed ruleset will have their sensitivity set to `medium`.
* All rules tagged with `<TAG_NAME>` will have their sensitivity set to `low`.
* The rule with ID `<MANAGED_RULESET_RULE_ID>` will use the `block` action.

The overrides apply to all packets matching the rule expression: `ip.dst in { 1.1.1.0/24 }`.

Request

```

curl --request PUT \

https://api.cloudflare.com/client/v4/accounts/{account_id}/rulesets/phases/ddos_l4/entrypoint \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "description": "Define overrides for the Network-layer DDoS Attack Protection managed ruleset",

  "rules": [

    {

      "action": "execute",

      "expression": "ip.dst in { 1.1.1.0/24 }",

      "action_parameters": {

        "id": "<MANAGED_RULESET_ID>",

        "overrides": {

          "sensitivity_level": "medium",

          "categories": [

            {

              "category": "<TAG_NAME>",

              "sensitivity_level": "low"

            }

          ],

          "rules": [

            {

              "id": "<MANAGED_RULESET_RULE_ID>",

              "action": "block"

            }

          ]

        }

      }

    }

  ]

}'


```

The response returns the created (or updated) phase entry point ruleset.

Response

```

{

  "result": {

    "id": "<PHASE_ENTRY_POINT_RULESET_ID>",

    "name": "default",

    "description": "Define overrides for the Network-layer DDoS Attack Protection managed ruleset",

    "kind": "root",

    "version": "1",

    "rules": [

      {

        "id": "<RULE_ID>",

        "version": "1",

        "action": "execute",

        "action_parameters": {

          "id": "<MANAGED_RULESET_ID>",

          "version": "latest",

          "overrides": {

            "categories": [

              {

                "category": "<TAG_NAME>",

                "sensitivity_level": "low"

              }

            ],

            "rules": [

              {

                "id": "<MANAGED_RULESET_RULE_ID>",

                "action": "block"

              }

            ],

            "sensitivity_level": "medium"

          }

        },

        "expression": "ip.dst in { 1.1.1.0/24 }",

        "last_updated": "2021-08-16T04:14:47.977741Z",

        "ref": "<RULE_REF>",

        "enabled": true

      }

    ],

    "last_updated": "2021-08-16T04:14:47.977741Z",

    "phase": "ddos_l4"

  }

}


```

For more information on defining overrides for managed rulesets using the Rulesets API, refer to [Override a managed ruleset](https://developers.cloudflare.com/ruleset-engine/managed-rulesets/override-managed-ruleset/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/network/","name":"Network-layer DDoS Attack Protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/managed-rulesets/network/network-overrides/","name":"Overrides"}},{"@type":"ListItem","position":6,"item":{"@id":"/ddos-protection/managed-rulesets/network/network-overrides/configure-api/","name":"Configure via API"}}]}
```

---

---
title: Configure in the dashboard
description: Create Network-layer DDoS Attack Protection overrides in the dashboard.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configure in the dashboard

Configure the Network-layer DDoS Attack Protection managed ruleset by defining [overrides](https://developers.cloudflare.com/ruleset-engine/managed-rulesets/override-managed-ruleset/) in the Cloudflare dashboard. DDoS overrides allow you to customize the **action** and **sensitivity** of one or more rules in the managed ruleset.

You define overrides for the Network-layer DDoS Attack Protection managed ruleset at the account level.

For more information on the available parameters and allowed values, refer to [Ruleset parameters](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/override-parameters/).

## Create a DDoS override

1. In the Cloudflare dashboard, go to the **L3/4 DDoS protection** page.  
[ Go to **DDoS Managed Rules** ](https://dash.cloudflare.com/?to=/:account/network-security/ddos)
2. Go to **Network-layer DDoS Protection**.
3. Select **Deploy a DDoS override**.
4. In **Set scope**, specify if you wish to apply the override to all incoming packets or to a subset of the packets.
5. If you are creating an override for a subset of the incoming packets, define the [custom expression](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/override-expressions/) that matches the incoming packets you wish to target in the override, using either the Rule Builder or the Expression Editor.
6. Select **Next**.
7. Depending on what you wish to override, refer to the following sections (you can perform both configurations on the same override):  
Configure all the rules in the ruleset (ruleset override)  
   1. Select **Next**.  
   2. Enter a name for your override in **Execution name**.  
   3. To always apply a given action for all the rules in the ruleset, select an action in **Ruleset action**.  
   4. To set the sensitivity level for all the rules in the ruleset, select a value in **Ruleset sensitivity**.  
Configure one or more rules  
   1. Search for the rules you wish to override using the available filters. You can search for tags.  
   2. To override a single rule, select the desired value for a field in the displayed dropdowns next to the rule.  
To configure more than one rule, select the rules using the row checkboxes and update the fields for the selected rules using the dropdowns displayed before the table. You can also configure all the rules with a given tag. For more information, refer to [Configure a managed ruleset](https://developers.cloudflare.com/waf/managed-rules/deploy-zone-dashboard/#configure-a-managed-ruleset). 14\. Select **Next**. 15\. Enter a name for your override in **Execution name**.  
Notes  
   * Tag and rule overrides have priority over ruleset overrides.  
   * The managed ruleset includes some read-only rules that you cannot override.
8. To save and deploy the override, select **Deploy**. If you are not ready to deploy your override, select **Save as Draft**.

### Delete a DDoS override

* [  New dashboard ](#tab-panel-7917)
* [ Old dashboard ](#tab-panel-7918)

1. In the Cloudflare dashboard, go to the **L3/4 DDoS protection** page.  
[ Go to **DDoS Managed Rules** ](https://dash.cloudflare.com/?to=/:account/network-security/ddos)
2. Go to the **Network-layer DDoS Protection** tab.
3. Select the override.
4. Select **Delete deployment**.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account.
2. Go to **Networking > L3/4 DDoS Protection**.
3. Next to the DDoS override you wish to delete, select **Delete**.
4. Select **Delete** to confirm the operation.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/network/","name":"Network-layer DDoS Attack Protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/managed-rulesets/network/network-overrides/","name":"Overrides"}},{"@type":"ListItem","position":6,"item":{"@id":"/ddos-protection/managed-rulesets/network/network-overrides/configure-dashboard/","name":"Configure in the dashboard"}}]}
```

---

---
title: Override examples
description: Example override configurations for Network-layer DDoS Attack Protection rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Override examples

## Use cases

The following scenarios detail how you can make use of override rules as a solution to common Network DDoS Protection issues.

### VPN traffic is blocked by a UDP rule

If you have VPN traffic concentrated to a single or a few single destination IP addresses and the traffic is being blocked by a UDP rule, you can create an override rule for the UDP rule to the destination IPs or ranges.

Note

The override only applies to the detection and not the fingerprint generated and used for mitigation. Refer to [Important remarks](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/override-expressions/#important-remarks) for more information.

### Attack traffic is flagged by the adaptive rule based on UDP and destination port

If you recognize that the traffic flagged by the adaptive rule based on UDP and destination port is an attack, you create an override rule to enable the adaptive rule in mitigation mode, setting the action to block the traffic.

### Minimize the risk of false positives impacting production traffic

To avoid disruptions during initial deployment, you can create a _Log_ only – _Essentially Off_ ruleset override that allows all traffic while logging detection results. This lets you safely observe and analyze DDoS activity before enabling enforcement.

1. In the Cloudflare dashboard, go to the **Security rules** page.  
[ Go to **Security rules** ](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. Go to the **DDoS protection** tab.
3. On **HTTP DDoS attack protection**, select **Create override**.
4. Set the **Scope** to _Apply to all incoming requests_.
5. Under **Ruleset configuration**:  
   * Set the **Ruleset action** to _Log_.  
   * Set the **Ruleset sensitivity** to _Essentially Off_.
6. Select **Save**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/network/","name":"Network-layer DDoS Attack Protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/managed-rulesets/network/network-overrides/","name":"Overrides"}},{"@type":"ListItem","position":6,"item":{"@id":"/ddos-protection/managed-rulesets/network/network-overrides/override-examples/","name":"Override examples"}}]}
```

---

---
title: Override expressions
description: Expression fields and operators for scoping Network-layer DDoS overrides.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Override expressions

Set an override expression for the Network-layer DDoS Attack Protection managed ruleset to define a specific scope for [sensitivity level](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/override-parameters/#sensitivity-level) or [action](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/override-parameters/#action) adjustments.

When considering which, if any, expressions you should utilize, think of expressions as a tool to scope overrides to the specific service that the Network-layer DDoS Attack Protection managed ruleset is protecting. That is to say that most services are defined by their destination ports and IPs as opposed to source ports or IPs. Refer to [Important remarks](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/override-expressions/#important-remarks) for more information.

For example, you can set different sensitivity levels for different destination IP addresses or ports: a medium sensitivity level for destination IP address `A` and a low sensitivity level for destination IP address `B`.

## Available expression fields

The following fields are made available for use in override expressions.

The list of fields we recommend using in expressions:

* `ip.dst`
* `ip.proto.num`
* `tcp.dstport`
* `tcp.flags`
* `tcp.flags.ack`
* `tcp.flags.fin`
* `tcp.flags.push`
* `tcp.flags.reset`
* `tcp.flags.syn`
* `tcp.flags.urg`
* `udp.dstport`

The list of fields we do not recommend to be used in expressions:

* `ip.src`
* `ip.len`
* `ip.ttl`
* `tcp.srcport`
* `udp.srcport`

Refer to the [Fields reference](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/) in the Rules language documentation for more information.

## Important remarks

### Recommended vs. non-recommended fields

Override expressions are not allowlists. Overrides are applied to the detection, and are not applied to the resulting mitigation. This means an override only takes effect if the attack fingerprint, as generated by the DDoS managed rules, includes the same fields specified in your expression. Thus, it makes the use of source fields like `ip.src`, `ip.len`, `ip.ttl`, `tcp.srcport`, and `udp.srcport` unreliable.

The use of non-recommended fields in an expression may result in unexpected behavior. While you may be inclined to utilize source properties, the expressions are not allowlists and including source traffic properties may result in false positives.

For example, if you create an override with sensitivity set to `Essentially Off` for `ip.src eq 192.0.2.1`, it only applies if the fingerprint includes `ip.src`. However, because DDoS attacks are often distributed across many source IPs, the fingerprint may not include `ip.src` at all. In such cases, your override is not applied.

In a common scenario, an attack originating from thousands of IPs can target a single destination IP and port. The fingerprint would focus on the shared attributes, such as the destination IP, port, and additional packet fields that represent strong signals of the attack pattern. Even if your override matches a specific source IP, it will not apply if that field is not present in the fingerprint. As a result, the system will mitigate the attack using the default high sensitivity, and traffic from your specified IP could still be blocked. It is recommended to use more stable expressions such as protocol, destination IP, and destination port.

### Character limits

Each expression is limited to 4,000 characters, which means you can enter approximately a maximum of 200 IP addresses in a single expression. However, you can enter IP addresses in CIDR format, which allows you to include a larger number of IP addresses. For example, you can use `192.0.0.0/24` to match IP addresses from `192.0.0.0` to `192.0.0.255`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/network/","name":"Network-layer DDoS Attack Protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/managed-rulesets/network/network-overrides/","name":"Overrides"}},{"@type":"ListItem","position":6,"item":{"@id":"/ddos-protection/managed-rulesets/network/network-overrides/override-expressions/","name":"Override expressions"}}]}
```

---

---
title: Parameters
description: Configurable parameters for Network-layer DDoS Attack Protection rule overrides.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Parameters

Define overrides for the Network-layer DDoS Attack Protection managed ruleset to change the action applied to a given attack or modify the sensitivity level of the detection mechanism. You can [define overrides in the Cloudflare dashboard](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/configure-dashboard/) or [define overrides via Rulesets API](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/configure-api/).

The available parameters are the following:

* Action
* Sensitivity Level

## Action

API property name: `"action"`.

The action performed for packets that match specific rules of Cloudflare's DDoS mitigation services. The available actions are:

* **Log**  
   * API value: `"log"`.  
   * Only available on Enterprise plans. Logs requests that match the expression of a rule detecting network layer DDoS attacks. Recommended for validating a rule before committing to a more severe action.  
   Refer to the [Analytics documentation](https://developers.cloudflare.com/analytics/network-analytics/configure/displayed-data/#view-logged-or-monitored-traffic) for more information on how to view logged or monitored traffic.
* **Block**  
   * API value: `"block"`.  
   * Blocks IP packets that match the rule expression given the sensitivity levels.
* **DDoS Dynamic**  
   * API value: _N/A_ (internal rule action that you cannot use in overrides).  
   * Performs a specific action according to a set of internal guidelines defined by Cloudflare. The executed action can be _Block_ or an undisclosed mitigation action.

## Sensitivity Level

API property name: `"sensitivity_level"`.

Defines how sensitive a rule is. Affects the thresholds used to determine if an attack should be mitigated. A higher sensitivity level means having a lower threshold, while a lower sensitivity level means having a higher threshold.

The available sensitivity levels are:

| UI value          | API value |
| ----------------- | --------- |
| _High_            | "default" |
| _Medium_          | "medium"  |
| _Low_             | "low"     |
| _Essentially Off_ | "eoff"    |

The default sensitivity level is _High_.

In most cases, when you select the _Essentially Off_ sensitivity level the rule will not trigger for any of the selected actions, including _Log_. However, if the attack is extremely large, Cloudflare's protection systems will still trigger the rule's mitigation action to protect Cloudflare's network.

_Essentially Off_ means that we have set an exceptionally low sensitivity level so in most cases traffic will not be mitigated for you. However, attack traffic will be mitigated at exceptional levels to ensure the safety and stability of the Cloudflare network.

**Log** means that requests will not be mitigated but only logged and shown on the dashboard. However, attack traffic will be mitigated at exceptional levels to ensure the safety and stability of the Cloudflare network.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/network/","name":"Network-layer DDoS Attack Protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/managed-rulesets/network/override-parameters/","name":"Parameters"}}]}
```

---

---
title: Rule categories
description: Categories of rules in the Network-layer DDoS Attack Protection managed ruleset.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Rule categories

The main categories (or tags) of Network-layer DDoS Attack Protection managed rules are the following:

| Name      | Description                                                                                                                                                                                                                                                                                                                                                                                                            |
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| gre       | Rules for DDoS attacks over Generic Routing Encapsulation (GRE) that usually target GRE endpoints.                                                                                                                                                                                                                                                                                                                     |
| esp       | Rules for DDoS attacks related to the Encapsulating Security Payload (ESP) protocol, which is part of the IPsec secure network protocol suite.                                                                                                                                                                                                                                                                         |
| advanced  | Rules related to features available to Enterprise customers, such as [Adaptive DDoS Protection](https://developers.cloudflare.com/ddos-protection/managed-rulesets/adaptive-protection/).                                                                                                                                                                                                                              |
| generic   | Rules for detecting and mitigating floods of packets. These rules are useful for mitigating attacks that have no known signatures, but they may also trigger on unusually high volumes of legitimate traffic. To reduce the risk of false positives, their packet per second (pps) activation threshold is higher. These rules rate-limit traffic by default, but you can override them to block traffic if necessary. |
| read-only | Highly targeted rules for mitigating DDoS attacks with a high confidence rate. These rules are read-only — you cannot override their sensitivity level or action.                                                                                                                                                                                                                                                      |
| test      | Rules used for testing the detection, mitigation, and alerting capabilities of Cloudflare's DDoS protection products.                                                                                                                                                                                                                                                                                                  |

There are other rule categories based on the attack vector/protocol, such as `dns`, `quic`, and `sip`. The categories list is dynamic and may change over time.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/managed-rulesets/","name":"Managed rulesets"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/managed-rulesets/network/","name":"Network-layer DDoS Attack Protection"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/managed-rulesets/network/rule-categories/","name":"Rule categories"}}]}
```

---

---
title: Botnet Threat Feed
description: Receive threat intelligence about DDoS botnets targeting your network infrastructure.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Botnet Threat Feed

The Cloudflare DDoS Botnet Threat Feed is a threat intelligence feed for service providers (SPs) such as hosting providers and Internet service providers (ISPs) that provides information about their own IP addresses that have participated in HTTP DDoS attacks as observed from Cloudflare's global network. The feed aims to help service providers stop the abuse and reduce DDoS attacks originating from within their networks.

Each offense is a mitigated HTTP request from the specific IP address. For example, if an IP has 3,000 offenses, it means that Cloudflare has mitigated 3,000 HTTP requests from that IP.

A service provider can only get information about IP addresses associated with their autonomous system numbers (ASNs). The affiliation of a service provider with their ASNs will be checked against [PeeringDB ↗](https://www.peeringdb.com/), a reliable and globally recognized interconnection database.

To ensure the feed's accuracy, Cloudflare will only include IP addresses that have participated in multiple HTTP DDoS attacks and have triggered high-confidence rules.

## Context

A single DDoS attack consisting of thousands of bots can involve as little as one single IP per service provider. Service providers usually only see a small fraction of the attack traffic leaving their network, and it can be hard to correlate it to malicious activity, while trying to identify abusers.

In the case of HTTPS DDoS attacks, service providers only see encrypted payloads leaving their network without any possibility to decrypt or understand if it is malicious or legitimate traffic. However, Cloudflare can see an entire attack and all of its sources if the attack targets an Internet property that uses Cloudflare's services. This global view can help service providers stop the abusers.

For more details, refer to [How DDoS protection works](https://developers.cloudflare.com/ddos-protection/about/how-ddos-protection-works/).

## Availability

The Cloudflare DDoS Botnet Threat Feed is available for free to service providers. For more information, refer to the [Terms of Use ↗](https://www.cloudflare.com/en-gb/service-specific-terms-application-services/#ddos-botnet-threat-feed).

---

## Before you begin

Make sure that:

* You have [created a Cloudflare account](https://developers.cloudflare.com/fundamentals/account/).

## Get started

### 1\. Authenticate your ASN via PeeringDB

1. In the Cloudflare dashboard, go to your account settings page.  
[ Go to **Configurations** ](https://dash.cloudflare.com/?to=/:account/configurations)
2. Select **DDoS Threat Feed ASNs**.
3. On the list of ASNs configured for your threat feed, select **Add ASN**.
4. You will be redirected to the PeeringDB authentication page, where you can log in and consent to share the affiliation data with us. You will be redirected back to the configuration page once it is successful.

Note

You can add multiple ASNs to your threat feed.

### 2\. Obtain Cloudflare API token

You must [obtain a Cloudflare API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) with at least the following account-level permission:

* _DDoS Botnet Feed_ \> _Read_

### 3\. Call Botnet Threat Feed API

Invoke one of the Botnet Threat Feed API endpoints:

* [Get full report](#get-full-report)
* [Get day report](#get-day-report)

---

## Available API endpoints

Important notes

* The API URI path is planned to change from `.../botnet_feed/...` to `.../ddos_botnet_feed/...` in the future.
* Responses with no IP addresses in the results (empty state) will return an `HTTP 200` status code (success), with an empty list in the `result` property.
* When the response is a success but the result is `0` or `null`, this means that there are no detected offenses.

To invoke an API endpoint, append the operation endpoint to the Cloudflare API base URL:

```

https://api.cloudflare.com/client/v4


```

### Get full report

Retrieves all the data in the botnet tracking database for a given ASN (currently two weeks worth of data).

* HTTP verb: `GET`
* Operation endpoint: `/accounts/{account_id}/botnet_feed/asn/{asn}/full_report`

The provided `{asn}` must be affiliated with your account.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DDoS Botnet Feed Write`
* `DDoS Botnet Feed Read`

Get full report

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/botnet_feed/asn/$ASN_ID/full_report" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

```

{

  "result": [

    {

      "cidr": "127.0.0.1/32",

      "date": "1970-01-01T00:00:00Z",

      "offense_count": 10000

    },

    // ... other entries ...

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

### Get day report

Retrieves all the data the botnet tracking database has for a given ASN on a given date. This operation currently allows dates greater than two weeks prior, but in this case it will return an empty dataset (the database currently stores two-weeks worth of data).

* HTTP verb: `GET`
* Operation endpoint: `/accounts/{account_id}/botnet_feed/asn/{asn}/day_report?date={date}`

The provided `{asn}` must be affiliated with your account.

`{date}` must be an ISO 8601-formatted date: `YYYY-MM-DD`. If no date is specified, the API responds with the data from the day before.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `DDoS Botnet Feed Write`
* `DDoS Botnet Feed Read`

Get daily report

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/botnet_feed/asn/$ASN_ID/day_report" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

```

{

  "result": [

    {

      "cidr": "127.0.0.1/32",

      "date": "2024-05-05T00:00:00Z",

      "offense_count": 10000

    },

    // ... other entries ...

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/botnet-threat-feed/","name":"Botnet Threat Feed"}}]}
```

---

---
title: FAQ
description: Answers to common questions about DDoS attack events, billing, and mitigation behavior.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# FAQ

## What is a DDoS attack event?

When Cloudflare's DDoS systems detect and mitigate attacks, they drop, rate-limit, or challenge (as applicable) packets, DNS queries, or HTTP requests, based on the type of attack.

There are three main DDoS mitigation systems:

1. [DDoS managed rulesets](https://developers.cloudflare.com/ddos-protection/managed-rulesets/)  
a. [Network-layer DDoS managed ruleset](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/)  
b. [HTTP DDoS managed ruleset](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/)
2. [Advanced TCP Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/)
3. [Advanced DNS Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-dns-protection/)

The DDoS managed ruleset includes many individual rules. Each rule provides the heuristics that instructs the system how to identify DDoS attack traffic. When the DDoS managed ruleset identifies an attack, it will generate a real-time fingerprint to match against the attack traffic, and install an ephemeral mitigation rule to mitigate the attack using that fingerprint.

The start time of the attack is when the mitigation rule is installed. The attack ends when there is no more traffic matching the rule. This is a single DDoS attack event.

A DDoS attack has a start time, end time, and additional attack metadata such as:

* Attack ID
* Attack vector
* Mitigating rule
* Total bytes and packets
* Attack target
* Mitigation action

This information is used to populate the [Executive Summary](https://developers.cloudflare.com/analytics/network-analytics/understand/main-dashboard/#executive-summary) section in the [Network Analytics](https://developers.cloudflare.com/analytics/network-analytics/) dashboard.

It can also be retrieved via GraphQL API using the `dosdAttackAnalyticsGroups` node.

Currently, the concept of a DDoS attack event only exists for the [Network-layer DDoS managed ruleset](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/). There is no such grouping of individual packets, queries, or HTTP requests for the other systems yet.

---

## How does Cloudflare protect against "low and slow" DDoS attacks?

A [low and slow DDoS attack ↗](https://www.cloudflare.com/learning/ddos/ddos-low-and-slow-attack/) is most commonly a non-volumetric attack. The attacker will send a low volume of HTTP requests, and do so slowly. This type of attack aims to be less detectable and slowly exhausts resources.

[Slowloris ↗](https://www.cloudflare.com/learning/ddos/ddos-attack-tools/slowloris/) is a type of low and slow attack where the attacker establishes [TCP connections](https://developers.cloudflare.com/fundamentals/reference/tcp-connections/) to the target server, often using HTTP or HTTPS protocols.

In the case of a Slowloris attack, the attacker sends incomplete HTTP header lines, thus never completing the HTTP request. The server waits for the complete request, holding the connection open. The attacker periodically sends additional HTTP header fields or partial lines to keep the connection alive. This can be achieved by sending partial HTTP headers, or using the `content-length` header to declare a message body size larger than what is actually sent.

The best practice to defend against low and slow attacks is by using an HTTP reverse proxy, such as Cloudflare's [CDN](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/) or [WAF](https://developers.cloudflare.com/waf/) service. The reverse proxy acts as a shield. It waits for a full HTTP request before forwarding it to the origin, serving from cache, or applying other actions based on user configuration. You can configure your zone so that requests are buffered by Cloudflare, which will absorb low and slow attacks. Our proxy waits for the full HTTP request before passing it on. To enable buffered requests, refer to [Request Body Buffering](https://developers.cloudflare.com/rules/configuration-rules/settings/#request-body-buffering).

The request will be served from Cloudflare's [Cache](https://developers.cloudflare.com/cache/) or [Workers](https://developers.cloudflare.com/workers/), if applicable. If not, it will only be sent to the origin — assuming it was fully completed and has passed WAF checks. So the attack does not exist, similar to TCP Slowloris attacks protection.

Additionally, the reverse proxy will timeout incomplete HTTP requests after a series of [keepalive probes](https://developers.cloudflare.com/fundamentals/reference/tcp-connections/#tcp-connections-and-keep-alives).

There is not a minimum threshold for activation. However, to provide additional security, custom firewall rules check for payload sizes and conducts basic sanity checks to ensure the content looks like what is expected.

The RUDY (R-U-Dead-Yet?) DDoS attack is another type of denial-of-service (DoS) tool that performs slow-rate attacks on targeted servers.

Unlike conventional DDoS attacks that overwhelm servers with a high volume of requests in a short period, RUDY focuses on creating a few prolonged requests. It does this by submitting form data at an extremely slow pace to keep the web server tied up and unavailable to legitimate traffic. This approach makes RUDY attacks difficult to detect, because the traffic can appear legitimate and does not flood the server with requests that would typically trigger conventional DDoS protection mechanisms​​​​​​.

RUDY specifically targets the application layer (Layer 7) of web servers by exploiting the way web forms handle data submission. The attack works by injecting one byte of information into an application `POST` field at a time, then waiting. This process causes application threads to await the completion of the form submission indefinitely, effectively exhausting the server's resources and preventing it from processing legitimate requests​​​​.

Refer to the [learning center ↗](https://www.cloudflare.com/learning/ddos/ddos-attack-tools/r-u-dead-yet-rudy/) for more information on RUDY attacks.

---

## How does Cloudflare deal with SSL/TLS negotiation attacks or floods?

SSL/TLS based attacks such as BEAST, Poodle, and CRIME are mitigated by Cloudflare's TLS settings, configuration, and cipher limitations. Because Cloudflare serves as the HTTP reverse proxy, TLS exhaustion style attacks are mitigated by terminating TLS sessions before passing HTTP requests to origin servers. TLS traffic is not proxied to origin servers without completing a proper TLS handshake. Additionally, our automated DDoS detection and mitigation systems leverage cipher suites, packet fields, HTTP request attributes and metadata, origin health, traffic profiling, Machine Learning models, and threat intelligence to detect and mitigate additional SSL-based attacks.

---

## Does Cloudflare use BGP Flowspec for upstream mitigation?

Yes. Using our anycast network, along with Traffic Manager, Unimog, and Plurimog, we conduct automated traffic engineering to spread the load of traffic (legitimate and attack) to ensure our network is performant, especially during mitigation of large attacks.

---

## Where can I see latest DDoS trends?

Cloudflare publishes quarterly DDoS reports and coverage of significant DDoS attacks. The publications are available on our [blog website ↗](https://blog.cloudflare.com/tag/ddos-reports/) and as interactive reports on the [Cloudflare Radar Reports website ↗](https://radar.cloudflare.com/reports?q=DDoS).

Learn more about the [methodologies](https://developers.cloudflare.com/radar/reference/quarterly-ddos-reports/) behind these reports.

You can also view [Cloudflare Radar ↗](https://radar.cloudflare.com/) for near real-time insights and trends.

---

## What is the Ping of Death DDoS attacks?

The Ping of Death (PoD) attack involves sending malformed or oversized packets to another computer or server, which can cause the system to freeze, crash, or reboot. Packets are pieces of data sent over the Internet, and the Ping of Death takes advantage of the fact that the IP protocol requires packets to be a maximum of 65,535 bytes in size. By sending a packet larger than this size, the attacker can exploit vulnerabilities in the target's TCP/IP stack, causing a buffer overflow and leading to unpredictable behavior, including system crashes. This type of attack is less common nowadays, as most modern systems and networking equipment have been patched to handle such anomalies.

---

## What are LOIC and HOIC?

LOIC is a popular network stress testing and DoS attack application that is used to flood a server with TCP, UDP, or HTTP requests with the intention of disrupting the service. It is known for its simplicity and ability to be used by individuals with minimal hacking experience. LOIC can be directed by the user to attack a small server, which can cause the server to slow down or crash from the overload of requests. It became famous around 2010 for its use by the hacker group Anonymous in attacks against major companies and organizations.

HOIC is an upgrade from LOIC, designed to overcome some of its limitations, especially in terms of detection and mitigation. It allows users to launch a more powerful DoS attack by enabling attacks on multiple websites at the same time with a higher volume of requests. HOIC also incorporates a feature that makes it more difficult for defense mechanisms to identify and mitigate the attack traffic, partly because it uses a technique that allows the traffic to mimic legitimate HTTP traffic, which is more challenging for traditional network security tools to detect. HOIC supports the use of "booster" scripts that enable it to target various websites simultaneously, significantly increasing its potency as a tool for conducting broad-scale DoS attacks.

These tools and attacks exploit different aspects of network protocols and behaviors to overwhelm targets with unwanted traffic, leading to denial of service. Due to their potential for abuse, their use is illegal and unethical outside of controlled environments for testing purposes.

---

## Can I exclude specific user agents from HTTP DDoS protection?

Yes, you can create an [override](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/override-expressions/) and use the expression fields to match against HTTP requests with the user agent. There are a variety of [fields](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/override-expressions/#available-expression-fields) that you can use.

You can then adjust the [sensitivity level](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/override-parameters/#sensitivity-level) or [mitigation action](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/override-parameters/#action).

Refer to the guide on how to [create an override](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/configure-dashboard/#create-a-ddos-override).

The use of expression fields is subject to [availability](https://developers.cloudflare.com/ddos-protection/#availability).

---

## Does Cloudflare charge for DDoS attack traffic?

No. Since 2017, Cloudflare offers [free, unmetered, and unlimited DDoS protection ↗](https://blog.cloudflare.com/unmetered-mitigation/). There is no limit to the number of DDoS attacks, their duration, or their size. Cloudflare's billing systems automatically exclude DDoS attack traffic from your usage.

---

## How does DDoS Protection determine whether a SYN flood attack is mitigated by `dosd` or Advanced TCP Protection?

DDoS [managed rules](https://developers.cloudflare.com/ddos-protection/managed-rulesets/) detect and mitigate attacks by finding commonality between attack packets and generating a real-time fingerprint to mitigate the attack.

When the attacks are highly randomized and DDoS managed rules are unable to detect a common pattern among the attack packets, [Advanced TCP Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/) uses its stateful TCP flowtracking capabilities to determine whether or not packets are legitimate. Advanced TCP Protection also mitigates simpler TCP-based attacks.

Advanced TCP Protection is only necessary and available to [Magic Transit](https://developers.cloudflare.com/magic-transit/) customers. For [Spectrum](https://developers.cloudflare.com/spectrum/) and our HTTP services, we leverage the reverse proxy to mitigate sophisticated randomized TCP-based DDoS attacks.

---

## How does Cloudflare handle hyper-localized DDoS attacks that may aim to overwhelm a specific Point of Presence (PoP)?

Hyper-localized DDoS attacks are attacks that target specific PoPs or data centers from botnet nodes that are close to those locations in an attempt to overwhelm them and cause an outage or service disruptions.

However, Cloudflare's defense approach is resilient to these attacks and uses a combination of intelligent traffic engineering, global Anycast, and real-time, autonomous DDoS mitigation to handle hyper-localized DDoS attacks — even those that may temporarily exceed the capacity of a specific Point of Presence (PoP).

### Global Anycast Network

Anycast allows multiple servers (PoPs) to share the same IP address, and the Border Gateway Protocol (BGP) routing system ensures user traffic is routed to the nearest or lowest-cost node.

#### Process

When one PoP is overwhelmed due to a local DDoS flood or as a result of limited capacity, BGP route propagation can be adjusted to shift traffic away from that PoP. Cloudflare can also withdraw BGP announcements from specific peers or upstreams to force traffic to reroute through better-equipped PoPs. Because DDoS traffic originates from multiple geographic regions, Anycast and traffic engineering distributes the attack across [Cloudflare's full capacity Anycast network ↗](https://www.cloudflare.com/network/) to reduce the burden on a single PoP.

### Intelligent Traffic Engineering

Cloudflare uses real-time data and intelligence systems to make decisions about traffic routing, load balancing, and congestion management.

#### Process

If a specific PoP becomes saturated or experiences attack traffic, Cloudflare's internal traffic engineering systems dynamically steer traffic across alternative paths using traffic shaping, path-aware routing, and dynamic DNS responses.

The system monitors CPU load, network congestion, and traffic type to make smart decisions about whether to reroute or throttle connections.

For Layer 7 (application-level) attacks, Cloudflare can challenge or rate-limit traffic before it reaches application servers. This scenario is similar to some extent to when we take down certain PoPs for maintenance. This can be done automatically via Traffic Manager, and if needed, by our Site Reliability Engineers (SRE).

### Real-Time DDoS Mitigation

DDoS managed rules and Advanced DDoS Protection are autonomous and run on every single server independently, while also coordinating locally and globally, contributing to the resilience of each server and PoP. These systems run close to the network edge in every PoP, meaning detection and mitigation happen rapidly, often before any noticeable impact. If traffic exceeds the capacity of one PoP, mitigation rules are replicated to other PoPs to help absorb overflow.

* **DDoS managed rules**: Detects and mitigates DDoS attacks in real-time. When it detects an attack, it deploys rules within seconds to mitigate the malicious traffic.
* **Advanced TCP Protection**: Identifies and drops abnormal TCP/IP behavior before it hits application servers.
* **Advanced DNS Protection**: Identifies and drops abnormal DNS queries behavior before it hits DNS servers.

---

## What is Advanced TCP Protection's Protected Learning functionality?

The Protected Learning functionality enables the [Advanced TCP Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/) system to overcome Internet routing chaos while allowing your legitimate traffic through and blocking DDoS attacks at the edge.

Anycast and BGP are protocols that help route Internet traffic by sending it to the nearest or most optimal data center. Occasional network events—such as a data center being taken offline for maintenance or changes in Internet routing—can cause an established connection to be rerouted to a different data center.

Cloudflare's flow inference functionality, also known as Protected Learning, is specifically designed to handle this. When a TCP connection, such as a flow, shifts to a new data center, our system observes that it is an existing connection that does not appear in the local flow table. Instead of immediately blocking the flow as an unknown connection that may be part of a DDoS attack, our system uses a proprietary process to verify if the connection is legitimate. It might challenge the acknowledgment (ACK) packets of the flow to ensure it is not part of a DDoS attack. Once the flow passes our checks, we allow it to continue without interruption. This ensures that even rare, legitimate shifts in traffic do not break your long-running connections while keeping your network protected against DDoS attacks.

---

## Does DDoS Protection protect against email-based attacks?

No. Cloudflare DDoS Protection safeguards web and network infrastructure against DDoS attacks at layers 3, 4, and 7 of the OSI model. This includes TCP, UDP, DNS, and HTTP/S traffic.

DDoS Protection does not inspect or mitigate threats delivered over email protocols such as SMTP, IMAP, or POP3\. To protect against email-borne threats such as phishing, business email compromise (BEC), spoofing, and malware delivered via email, use [Cloudflare Email Security](https://developers.cloudflare.com/email-security/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/frequently-asked-questions/","name":"FAQ"}}]}
```

---

---
title: Changelog
description: Stay updated with Cloudflare's DDoS protection. Discover the latest rule updates, accuracy improvements, and threat landscape adaptations.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Changelog

Cloudflare has a regular cadence of releasing updates and new rules to the DDoS managed rulesets. The updates either improve a rule's accuracy, lower false positives rates, or increase the protection due to a change in the threat landscape.

The release cycle for a new rule within the regular cadence follows this process:

* Cloudflare adds a new rule configured with the _Log_ action, and announces the rule in the "Scheduled changes" section of each managed ruleset.
* From that point on, if this rule matches any traffic, the matched traffic will be visible in one of the [analytics dashboards](https://developers.cloudflare.com/ddos-protection/reference/analytics/). If you suspect this might be a false positive, you can lower the sensitivity for that rule. Refer to [override examples](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/http-overrides/override-examples/#legitimate-traffic-is-incorrectly-identified-as-an-attack-and-causes-a-false-positive) for details.
* Cloudflare updates the rule action to mitigate traffic (for example, using the _Block_ action) after a period of at least seven days, usually on a Monday. The exact date is shown in the scheduled changes list.

Changes to existing rules follow the same process, except that Cloudflare will create a temporary updated rule (denoted as `BETA` in rule description) before updating the original rule on the next release cycle.

Cloudflare is very proactive in responding to new attack vectors, which may need to be released outside of the 7-day cycle, defined as an Emergency Release. This emergency release is only used to respond to new high priority threats with a low false positive probability.

## RSS feeds

* [General updates](https://developers.cloudflare.com/ddos-protection/change-log/general-updates/) \- [ Subscribe to RSS ](https://developers.cloudflare.com/ddos-protection/change-log/general-updates/index.xml)
* [Network-layer DDoS managed ruleset](https://developers.cloudflare.com/ddos-protection/change-log/network/) \- [ Subscribe to RSS ](https://developers.cloudflare.com/ddos-protection/change-log/network/index.xml)
* [HTTP DDoS managed ruleset](https://developers.cloudflare.com/ddos-protection/change-log/http/) \- [ Subscribe to RSS ](https://developers.cloudflare.com/ddos-protection/change-log/http/index.xml)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}}]}
```

---

---
title: General updates
description: General updates and improvements to Cloudflare DDoS protection.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# General updates

[ Subscribe to RSS ](https://developers.cloudflare.com/ddos-protection/change-log/general-updates/index.xml)

## 2024-06-03

**DDoS alerts now available for EU CMB customers**

[DDoS alerts](https://developers.cloudflare.com/ddos-protection/reference/alerts/) are now available for EU Customer Metadata Boundary (CMB) customers. This includes all DDoS alert type (Standard and Advanced) for both HTTP DDoS attacks and L3/4 DDoS attacks.

## 2024-04-17

**Network Analytics now supported for EU CMB customers**

The Network Analytics dashboard is available to customers that have opted in to the EU [Customer Metadata Boundary](https://developers.cloudflare.com/data-localization/metadata-boundary/) (CMB) solution. This also includes Network Analytics Logs (Logpush) and GraphQL API.

API users can ensure they are routed properly by directing their API requests at `eu.api.cloudflare.com`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/general-updates/","name":"General updates"}}]}
```

---

---
title: HTTP DDoS managed ruleset
description: Changelog of rule updates for the HTTP DDoS Attack Protection managed ruleset.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# HTTP DDoS managed ruleset

This section contains past and upcoming changes to the [HTTP DDoS Attack Protection managed ruleset](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/).

[ View scheduled changes ](https://developers.cloudflare.com/ddos-protection/change-log/http/scheduled-changes/) [ Subscribe to RSS ](https://developers.cloudflare.com/ddos-protection/change-log/http/index.xml) 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}}]}
```

---

---
title: 2022-04-07
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-04-07

| Rule ID     | Description                  | Previous Action | New Action    | Notes                                                    |
| ----------- | ---------------------------- | --------------- | ------------- | -------------------------------------------------------- |
| ...8ed59b32 | Global L7 attack mitigations | ddos\_dynamic   | ddos\_dynamic | Some attack patterns will be detected more consistently. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-04-07/","name":"2022-04-07"}}]}
```

---

---
title: 2022-04-12
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-04-12

| Rule ID     | Description                                                          | Previous Action | New Action         | Notes                                                              |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------------ | ------------------------------------------------------------------ |
| ...61b90333 | HTTP requests with unusual HTTP headers or URI path (signature #15). | N/A             | managed\_challenge | This rule is detecting floods of requests impersonating a browser. |
| ...81b13394 | HTTP requests with unusual HTTP headers or URI path (signature #2).  | block           | block              | Updated the filter to detect attacks more easily                   |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-04-12/","name":"2022-04-12"}}]}
```

---

---
title: 2022-04-21
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-04-21

| Rule ID     | Description                                     | Previous Action | New Action | Notes                   |
| ----------- | ----------------------------------------------- | --------------- | ---------- | ----------------------- |
| ...e7dccda4 | HTTP requests from known botnet (signature #7). | block           | block      | Remove false positives. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-04-21/","name":"2022-04-21"}}]}
```

---

---
title: 2022-05-03
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-05-03

| Rule ID     | Description                                                                | Previous Action | New Action | Notes                                              |
| ----------- | -------------------------------------------------------------------------- | --------------- | ---------- | -------------------------------------------------- |
| ...4cc1fcb6 | BETA - HTTP requests with unusual HTTP headers or URI path (signature #2). | log             | N/A        |                                                    |
| ...81b13394 | HTTP requests with unusual HTTP headers or URI path (signature #2).        | block           | block      | Update the rule to catch more attacks than before. |
| ...863134d5 | HTTP requests from known bad user agents.                                  | log             | block      |                                                    |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-05-03/","name":"2022-05-03"}}]}
```

---

---
title: 2022-05-12
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-05-12

| Rule ID     | Description                                                         | Previous Action | New Action | Notes |
| ----------- | ------------------------------------------------------------------- | --------------- | ---------- | ----- |
| ...ad07ec62 | HTTP requests with unusual HTTP headers or URI path (signature #6). | log             | block      |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-05-12/","name":"2022-05-12"}}]}
```

---

---
title: 2022-06-01
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-06-01

| Rule ID     | Description                                   | Previous Action    | New Action    | Notes                                                       |
| ----------- | --------------------------------------------- | ------------------ | ------------- | ----------------------------------------------------------- |
| ...d2f294d7 | HTTP requests trying to impersonate browsers. | managed\_challenge | ddos\_dynamic | Pick different actions depending on attack characteristics. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-06-01/","name":"2022-06-01"}}]}
```

---

---
title: 2022-06-08
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-06-08

| Rule ID     | Description                                   | Previous Action | New Action    | Notes                                      |
| ----------- | --------------------------------------------- | --------------- | ------------- | ------------------------------------------ |
| ...d2f294d7 | HTTP requests trying to impersonate browsers. | ddos\_dynamic   | ddos\_dynamic | Expanded the filter to catch more attacks. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-06-08/","name":"2022-06-08"}}]}
```

---

---
title: 2022-07-06
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-07-06

| Rule ID     | Description                                                                                     | Previous Action | New Action | Notes                                                                                                                                                                                                                                                                                                                       |
| ----------- | ----------------------------------------------------------------------------------------------- | --------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ...444be2c3 | Location-Aware DDoS Protection (Available only to Enterprise zones with Advanced DDoS service). | N/A             | log        | Added new Location-Aware DDoS Protection for Enterprise accounts that are subscribed to the Advanced DDoS service. Location Aware DDoS Protection constantly learns a zone's traffic levels per country and region over time, creates a traffic profile and then flags or mitigates traffic that deviates from the profile. |
| ...863134d5 | HTTP requests from known bad user agents.                                                       | block           | block      | Requests matching this rule will not match any other.                                                                                                                                                                                                                                                                       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-07-06/","name":"2022-07-06"}}]}
```

---

---
title: 2022-07-08
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-07-08

| Rule ID     | Description                                                            | Previous Action | New Action    | Notes                                                                     |
| ----------- | ---------------------------------------------------------------------- | --------------- | ------------- | ------------------------------------------------------------------------- |
| ...7d4f6798 | HTTP requests causing a high request rate to authentication endpoints. | block           | block         | Update thresholds for lower sensitivity levels to align with other rules. |
| ...ecd68c61 | HTTP requests causing a high request rate to search endpoints.         | ddos\_dynamic   | ddos\_dynamic | Update thresholds for lower sensitivity levels to align with other rules. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-07-08/","name":"2022-07-08"}}]}
```

---

---
title: 2022-07-18
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-07-18

| Rule ID     | Description                                                          | Previous Action | New Action | Notes                         |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | ----------------------------- |
| ...1712a123 | HTTP requests with unusual HTTP headers or URI path (signature #16). | log             | block      | Enable the rule as scheduled. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-07-18/","name":"2022-07-18"}}]}
```

---

---
title: 2022-08-02
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-08-02

| Rule ID     | Description                                                          | Previous Action | New Action    | Notes                                                                                      |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------- | ------------------------------------------------------------------------------------------ |
| ...1712a123 | HTTP requests with unusual HTTP headers or URI path (signature #16). | log             | block         | Allow requests matching this rule to match other rules too in order to catch more attacks. |
| ...d2f294d7 | HTTP requests trying to impersonate browsers.                        | ddos\_dynamic   | ddos\_dynamic | Extend the scope of this filter to match a wider set of requests.                          |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-08-02/","name":"2022-08-02"}}]}
```

---

---
title: 2022-08-10
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-08-10

| Rule ID     | Description                                   | Previous Action | New Action    | Notes                   |
| ----------- | --------------------------------------------- | --------------- | ------------- | ----------------------- |
| ...d2f294d7 | HTTP requests trying to impersonate browsers. | ddos\_dynamic   | ddos\_dynamic | Remove false positives. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-08-10/","name":"2022-08-10"}}]}
```

---

---
title: 2022-08-16
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-08-16

| Rule ID     | Description                                                                 | Previous Action | New Action | Notes                                                           |
| ----------- | --------------------------------------------------------------------------- | --------------- | ---------- | --------------------------------------------------------------- |
| ...1712a123 | HTTP requests with unusual HTTP headers or URI path (signature #16).        | block           | block      | Modify the rule to catch more attacks.                          |
| ...b757316c | BETA - HTTP requests with unusual HTTP headers or URI path (signature #16). | log             | N/A        | Observation filter removed, rule is now merged with ...1712a123 |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-08-16/","name":"2022-08-16"}}]}
```

---

---
title: 2022-09-13
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-09-13

| Rule ID     | Description                                                                                       | Previous Action | New Action         | Notes |
| ----------- | ------------------------------------------------------------------------------------------------- | --------------- | ------------------ | ----- |
| ...e4fe8e55 | User-Agent-aware DDoS Protection (Available only to Enterprise zones with Advanced DDoS service). | log             | managed\_challenge |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-09-13/","name":"2022-09-13"}}]}
```

---

---
title: 2022-09-14
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-09-14

| Rule ID     | Description                                                                                       | Previous Action    | New Action | Notes                                                                                                              |
| ----------- | ------------------------------------------------------------------------------------------------- | ------------------ | ---------- | ------------------------------------------------------------------------------------------------------------------ |
| ...e4fe8e55 | User-Agent-aware DDoS Protection (Available only to Enterprise zones with Advanced DDoS service). | managed\_challenge | log        | This rule is causing false positive in some rare occurrences, we are reverting it back to log by default (opt-in). |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-09-14/","name":"2022-09-14"}}]}
```

---

---
title: 2022-09-19 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-09-19 - Emergency

| Rule ID     | Description                                     | Previous Action | New Action    | Notes                                                |
| ----------- | ----------------------------------------------- | --------------- | ------------- | ---------------------------------------------------- |
| ...c4bef55c | HTTP requests from known botnet (signature #5). | ddos\_dynamic   | ddos\_dynamic | Update the rule to target previously missed attacks. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-09-19-emergency/","name":"2022-09-19 - Emergency"}}]}
```

---

---
title: 2022-10-06 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-10-06 - Emergency

| Rule ID     | Description                                              | Previous Action    | New Action    | Notes                                                                                    |
| ----------- | -------------------------------------------------------- | ------------------ | ------------- | ---------------------------------------------------------------------------------------- |
| ...6fa59d23 | HTTP requests that are very likely coming from bots.     | managed\_challenge | ddos\_dynamic | Block very large attacks instead of challenging them.                                    |
| ...91b2849e | HTTP requests with unusual HTTP headers (signature #13). | block              | block         | Some attacks were only partially mitigated. Now the rule should stop attacks completely. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-10-06-emergency/","name":"2022-10-06 - Emergency"}}]}
```

---

---
title: 2022-10-14
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-10-14

| Rule ID     | Description                                          | Previous Action | New Action    | Notes                                            |
| ----------- | ---------------------------------------------------- | --------------- | ------------- | ------------------------------------------------ |
| ...6fa59d23 | HTTP requests that are very likely coming from bots. | ddos\_dynamic   | ddos\_dynamic | Block more large attacks instead of challenging. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-10-14/","name":"2022-10-14"}}]}
```

---

---
title: 2022-11-02 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-11-02 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action | Notes                                  |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | -------------------------------------- |
| ...06a46ce3 | HTTP requests with unusual HTTP headers or URI path (signature #18). | N/A             | block      | N/A                                    |
| ...81b5405c | HTTP requests from known botnet (signature #3).                      | block           | block      | Extend the rule to catch more attacks. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-11-02-emergency/","name":"2022-11-02 - Emergency"}}]}
```

---

---
title: 2022-12-07 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2022-12-07 - Emergency

| Rule ID     | Description                                   | Previous Action | New Action    | Notes                                                                 |
| ----------- | --------------------------------------------- | --------------- | ------------- | --------------------------------------------------------------------- |
| ...d2f294d7 | HTTP requests trying to impersonate browsers. | ddos\_dynamic   | ddos\_dynamic | Remove a small probability of false positive with worker subrequests. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2022-12-07-emergency/","name":"2022-12-07 - Emergency"}}]}
```

---

---
title: 2023-01-30
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-01-30

| Rule ID     | Description                                                          | Previous Action | New Action | Notes                                               |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | --------------------------------------------------- |
| ...291a3fc7 | HTTP requests with unusual HTTP headers or URI path (signature #19). | log             | block      | New rule blocking requests with unusual attributes. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-01-30/","name":"2023-01-30"}}]}
```

---

---
title: 2023-02-20
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-02-20

| Rule ID     | Description                               | Previous Action | New Action | Notes                                 |
| ----------- | ----------------------------------------- | --------------- | ---------- | ------------------------------------- |
| ...863134d5 | HTTP requests from known bad user agents. | block           | block      | Detect more load testing tools as bad |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-02-20/","name":"2023-02-20"}}]}
```

---

---
title: 2023-02-28 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-02-28 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action    | Notes                                                                           |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------- | ------------------------------------------------------------------------------- |
| ...97003a74 | HTTP requests with unusual HTTP headers or URI path (signature #17). | log             | ddos\_dynamic | Enable mitigation on a subset of this rule that is known to only match attacks. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-02-28-emergency/","name":"2023-02-28 - Emergency"}}]}
```

---

---
title: 2023-03-10
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-03-10

| Rule ID     | Description                                                          | Previous Action | New Action    | Notes                                            |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------- | ------------------------------------------------ |
| ...97003a74 | HTTP requests with unusual HTTP headers or URI path (signature #17). | ddos\_dynamic   | block         | Detect new attacks with unusual HTTP attributes. |
| ...d2f294d7 | HTTP requests trying to impersonate browsers.                        | ddos\_dynamic   | ddos\_dynamic | Expand the filter to catch more attacks.         |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-03-10/","name":"2023-03-10"}}]}
```

---

---
title: 2023-03-22
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-03-22

| Rule ID     | Description                                   | Previous Action | New Action    | Notes                                                                                          |
| ----------- | --------------------------------------------- | --------------- | ------------- | ---------------------------------------------------------------------------------------------- |
| ...d2f294d7 | HTTP requests trying to impersonate browsers. | ddos\_dynamic   | ddos\_dynamic | Mitigate more attacks (action is managed-challenge for smaller attacks, block for large ones). |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-03-22/","name":"2023-03-22"}}]}
```

---

---
title: 2023-04-03
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-04-03

| Rule ID     | Description                                   | Previous Action | New Action | Notes |
| ----------- | --------------------------------------------- | --------------- | ---------- | ----- |
| ...cedf44f8 | HTTP requests with non-standard HTTP methods. | log             | block      |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-04-03/","name":"2023-04-03"}}]}
```

---

---
title: 2023-04-17
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-04-17

Previously, only a subset of rules were exposed publicly. In rare situations, these rules can cause false positives. When this happens, you can customize their behavior using overrides.

Besides these rules, the DDoS managed rules contain other rules that do not cause issues. Until now, these rules were not shown in the dashboard or referenced in the documentation.

Cloudflare now shows all rules in the dashboard, including these high-confidence rules. This means that requests matching these rules will now have the correct rule identifier. The newly published rules are read-only and you cannot disable them.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-04-17/","name":"2023-04-17"}}]}
```

---

---
title: 2023-04-21 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-04-21 - Emergency

| Rule ID     | Description                                      | Previous Action | New Action    | Notes                             |
| ----------- | ------------------------------------------------ | --------------- | ------------- | --------------------------------- |
| ...d2f294d7 | HTTP requests trying to impersonate browsers.    | ddos\_dynamic   | ddos\_dynamic | Remove some rare false positives. |
| ...d3fb9259 | HTTP requests from known botnet (signature #51). | N/A             | block         |                                   |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-04-21-emergency/","name":"2023-04-21 - Emergency"}}]}
```

---

---
title: 2023-04-27 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-04-27 - Emergency

| Rule ID     | Description                                   | Previous Action | New Action    | Notes |
| ----------- | --------------------------------------------- | --------------- | ------------- | ----- |
| ...f2494447 | HTTP requests attempting to bypass the cache. | N/A             | ddos\_dynamic |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-04-27-emergency/","name":"2023-04-27 - Emergency"}}]}
```

---

---
title: 2023-05-02 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-05-02 - Emergency

| Rule ID     | Description                                   | Previous Action | New Action    | Notes                                                        |
| ----------- | --------------------------------------------- | --------------- | ------------- | ------------------------------------------------------------ |
| ...d2f294d7 | HTTP requests trying to impersonate browsers. | ddos\_dynamic   | ddos\_dynamic | Improve our capability to efficiently identify some attacks. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-05-02-emergency/","name":"2023-05-02 - Emergency"}}]}
```

---

---
title: 2023-05-15 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-05-15 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action    | Notes                                                        |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------- | ------------------------------------------------------------ |
| ...1fc1e601 | HTTP requests with unusual HTTP headers or URI path (signature #31). | N/A             | block         |                                                              |
| ...863134d5 | HTTP requests from known bad user agents.                            | block           | block         | Widen detection scope.                                       |
| ...bb3cefd0 | HTTP requests with unusual HTTP headers or URI path (signature #53). | N/A             | block         |                                                              |
| ...d2f294d7 | HTTP requests trying to impersonate browsers.                        | ddos\_dynamic   | ddos\_dynamic | Extend the rule to catch attacks across multiple subdomains. |
| ...d2f294d7 | HTTP requests trying to impersonate browsers.                        | ddos\_dynamic   | ddos\_dynamic | Expand the filter to catch more attacks.                     |
| ...f2494447 | HTTP requests attempting to bypass the cache.                        | ddos\_dynamic   | ddos\_dynamic | Make rule more accurate when blocking attacks.               |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-05-15-emergency/","name":"2023-05-15 - Emergency"}}]}
```

---

---
title: 2023-05-16 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-05-16 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action    | Notes                               |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------- | ----------------------------------- |
| ...311e414e | HTTP requests with unusual HTTP headers or URI path (signature #33). | N/A             | ddos\_dynamic | Stop attacks from an active botnet. |
| ...ad16b3fb | HTTP requests from known botnet (signature #54).                     | N/A             | block         |                                     |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-05-16-emergency/","name":"2023-05-16 - Emergency"}}]}
```

---

---
title: 2023-05-22
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-05-22

| Rule ID     | Description                                                          | Previous Action | New Action | Notes                      |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | -------------------------- |
| ...4a95ba67 | HTTP requests with unusual HTTP headers or URI path (signature #32). | log             | log        | Improve the rule accuracy. |
| ...fd5045ff | HTTP requests from known botnet (signature #55).                     | N/A             | block      |                            |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-05-22/","name":"2023-05-22"}}]}
```

---

---
title: 2023-05-26
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-05-26

| Rule ID     | Description                                                          | Previous Action | New Action    | Notes |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------- | ----- |
| ...4a95ba67 | HTTP requests with unusual HTTP headers or URI path (signature #32). | log             | ddos\_dynamic |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-05-26/","name":"2023-05-26"}}]}
```

---

---
title: 2023-06-05 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-06-05 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action | Notes                               |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | ----------------------------------- |
| ...6831bff1 | HTTP requests with unusual HTTP headers or URI path (signature #35). | N/A             | block      | Stop attacks from an active botnet. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-06-05-emergency/","name":"2023-06-05 - Emergency"}}]}
```

---

---
title: 2023-06-06
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-06-06

| Rule ID     | Description                                                          | Previous Action | New Action | Notes |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | ----- |
| ...6831bff1 | HTTP requests with unusual HTTP headers or URI path (signature #35). | N/A             | block      |       |
| ...72bb7bfd | HTTP requests with unusual HTTP headers or URI path (signature #34). | N/A             | block      |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-06-06/","name":"2023-06-06"}}]}
```

---

---
title: 2023-06-14 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-06-14 - Emergency

| Rule ID     | Description                                          | Previous Action | New Action    | Notes                                    |
| ----------- | ---------------------------------------------------- | --------------- | ------------- | ---------------------------------------- |
| ...6fa59d23 | HTTP requests that are very likely coming from bots. | ddos\_dynamic   | ddos\_dynamic | Expand the filter to match more attacks. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-06-14-emergency/","name":"2023-06-14 - Emergency"}}]}
```

---

---
title: 2023-06-16
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-06-16

| Rule ID     | Description                                      | Previous Action | New Action | Notes |
| ----------- | ------------------------------------------------ | --------------- | ---------- | ----- |
| ...21e99dcf | HTTP requests from known botnet (signature #58). | N/A             | block      |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-06-16/","name":"2023-06-16"}}]}
```

---

---
title: 2023-06-19
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-06-19

| Rule ID     | Description                                      | Previous Action | New Action | Notes |
| ----------- | ------------------------------------------------ | --------------- | ---------- | ----- |
| ...de244156 | HTTP requests from known botnet (signature #59). | N/A             | block      |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-06-19/","name":"2023-06-19"}}]}
```

---

---
title: 2023-06-28
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-06-28

| Rule ID     | Description                                                                                                | Previous Action | New Action    | Notes |
| ----------- | ---------------------------------------------------------------------------------------------------------- | --------------- | ------------- | ----- |
| ...95f78bf0 | HTTP requests trying to impersonate browsers (pattern #2).                                                 | log             | ddos\_dynamic |       |
| ...c86adf25 | HTTP requests with unusual HTTP headers or URI path (signature #38). Only for zones on PRO plan and above. | log             | ddos\_dynamic |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-06-28/","name":"2023-06-28"}}]}
```

---

---
title: 2023-07-06
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-07-06

| Rule ID     | Description                       | Previous Action | New Action         | Notes |
| ----------- | --------------------------------- | --------------- | ------------------ | ----- |
| ...22807318 | HTTP requests from known botnets. | log             | managed\_challenge |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-07-06/","name":"2023-07-06"}}]}
```

---

---
title: 2023-07-07
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-07-07

| Rule ID     | Description                                      | Previous Action | New Action         | Notes |
| ----------- | ------------------------------------------------ | --------------- | ------------------ | ----- |
| ...22807318 | HTTP requests from known botnets.                | log             | managed\_challenge |       |
| ...83dc0d58 | HTTP requests from known botnet (signature #60). | N/A             | block              |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-07-07/","name":"2023-07-07"}}]}
```

---

---
title: 2023-07-12 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-07-12 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action    | Notes |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------- | ----- |
| ...0d5872e3 | HTTP requests with unusual HTTP headers or URI path (signature #40). | N/A             | ddos\_dynamic |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-07-12-emergency/","name":"2023-07-12 - Emergency"}}]}
```

---

---
title: 2023-07-17
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-07-17

| Rule ID     | Description                                                          | Previous Action | New Action | Notes                                     |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | ----------------------------------------- |
| ...6831bff1 | HTTP requests with unusual HTTP headers or URI path (signature #35). | ddos\_dynamic   | block      | Improve the filter to catch more attacks. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-07-17/","name":"2023-07-17"}}]}
```

---

---
title: 2023-07-31
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-07-31

| Rule ID     | Description                                      | Previous Action | New Action | Notes                                                                                      |
| ----------- | ------------------------------------------------ | --------------- | ---------- | ------------------------------------------------------------------------------------------ |
| ...9aec0913 | HTTP requests from known botnet (signature #52). | block           | block      | Expose existing read-only filter publicly as it might cause false positives in rare cases. |
| ...c5f479f0 | HTTP requests from known botnet (signature #62). | N/A             | block      |                                                                                            |
| ...d0e36f9c | HTTP requests from known botnet (signature #63). | N/A             | block      |                                                                                            |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-07-31/","name":"2023-07-31"}}]}
```

---

---
title: 2023-08-11 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-08-11 - Emergency

| Rule ID     | Description                                                          | Previous Action    | New Action    | Notes |
| ----------- | -------------------------------------------------------------------- | ------------------ | ------------- | ----- |
| ...1de9523e | HTTP requests with unusual HTTP headers or URI path (signature #41). | N/A                | block         |       |
| ...22807318 | HTTP requests from known botnets.                                    | managed\_challenge | ddos\_dynamic |       |
| ...aa03a345 | HTTP requests from known botnet (signature #68).                     | N/A                | block         |       |
| ...efca86eb | HTTP requests from known botnet (signature #66).                     | N/A                | block         |       |
| ...f93fb5d6 | HTTP requests from known botnet (signature #67).                     | N/A                | block         |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-08-11-emergency/","name":"2023-08-11 - Emergency"}}]}
```

---

---
title: 2023-08-14
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-08-14

| Rule ID     | Description                                   | Previous Action | New Action         | Notes                                    |
| ----------- | --------------------------------------------- | --------------- | ------------------ | ---------------------------------------- |
| ...22807318 | HTTP requests from known botnets.             | ddos\_dynamic   | managed\_challenge | Expand the filter to catch more attacks. |
| ...d2f294d7 | HTTP requests trying to impersonate browsers. | ddos\_dynamic   | ddos\_dynamic      | Expand the filter to catch more attacks. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-08-14/","name":"2023-08-14"}}]}
```

---

---
title: 2023-08-16 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-08-16 - Emergency

| Rule ID     | Description                                                | Previous Action | New Action    | Notes |
| ----------- | ---------------------------------------------------------- | --------------- | ------------- | ----- |
| ...9721fd20 | HTTP requests trying to impersonate browsers (pattern #3). | N/A             | ddos\_dynamic |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-08-16-emergency/","name":"2023-08-16 - Emergency"}}]}
```

---

---
title: 2023-08-25 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-08-25 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action | Notes                                                                                                              |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | ------------------------------------------------------------------------------------------------------------------ |
| ...20c5afb5 | HTTP requests with unusual HTTP headers or URI path (signature #36). | block           | block      | This rule was previously readonly, but can cause false positives in rare cases. It is now possible to override it. |
| ...cb26e2e2 | HTTP requests from known botnet (signature #69).                     | N/A             | block      |                                                                                                                    |
| ...ebff5ef1 | HTTP requests with unusual HTTP headers or URI path (signature #43). | N/A             | block      |                                                                                                                    |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-08-25-emergency/","name":"2023-08-25 - Emergency"}}]}
```

---

---
title: 2023-08-29 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-08-29 - Emergency

| Rule ID     | Description                                                          | Previous Action    | New Action    | Notes |
| ----------- | -------------------------------------------------------------------- | ------------------ | ------------- | ----- |
| ...22807318 | HTTP requests from known botnets.                                    | managed\_challenge | ddos\_dynamic |       |
| ...3fe55678 | HTTP requests with unusual HTTP headers or URI path (signature #44). | N/A                | block         |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-08-29-emergency/","name":"2023-08-29 - Emergency"}}]}
```

---

---
title: 2023-08-30 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-08-30 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action    | Notes |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------- | ----- |
| ...22807318 | HTTP requests from known botnets.                                    | ddos\_dynamic   | ddos\_dynamic |       |
| ...46082508 | HTTP requests with unusual HTTP headers or URI path (signature #45). | N/A             | block         |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-08-30-emergency/","name":"2023-08-30 - Emergency"}}]}
```

---

---
title: 2023-09-05 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-09-05 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action    | Notes                                                        |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------- | ------------------------------------------------------------ |
| ...22807318 | HTTP requests from known botnets.                                    | ddos\_dynamic   | ddos\_dynamic | Expand filter to catch attacks more comprehensively.         |
| ...4346874d | HTTP requests with unusual HTTP headers or URI path (signature #46). | N/A             | block         |                                                              |
| ...6fe7a312 | HTTP requests from known botnet (signature #70).                     | N/A             | block         | Expand filter to catch more attacks. It is now configurable. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-09-05-emergency/","name":"2023-09-05 - Emergency"}}]}
```

---

---
title: 2023-09-21 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-09-21 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action    | Notes                                                                      |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------- | -------------------------------------------------------------------------- |
| ...1d73128d | HTTP requests from known botnet (signature #56).                     | block           | block         | Make the rule customizable as it might cause false positive in rare cases. |
| ...4a95ba67 | HTTP requests with unusual HTTP headers or URI path (signature #32). | ddos\_dynamic   | ddos\_dynamic | Expand the scope of the rule to catch more attacks.                        |
| ...6fe7a312 | HTTP requests from known botnet (signature #70).                     | block           | block         | Update the rule to remove some rare false positives.                       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-09-21-emergency/","name":"2023-09-21 - Emergency"}}]}
```

---

---
title: 2023-09-24 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-09-24 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action | Notes                              |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | ---------------------------------- |
| ...0fb54442 | HTTP requests with unusual HTTP headers or URI path (signature #49). | N/A             | block      |                                    |
| ...3dd5f188 | HTTP requests from known botnet (signature #71).                     | N/A             | block      |                                    |
| ...97003a74 | HTTP requests with unusual HTTP headers or URI path (signature #17). | block           | block      | Expand rule to catch more attacks. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-09-24-emergency/","name":"2023-09-24 - Emergency"}}]}
```

---

---
title: 2023-10-09 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-10-09 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action | Notes |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | ----- |
| ...02bbdce1 | HTTP requests with unusual HTTP headers or URI path (signature #47). | N/A             | block      |       |
| ...493cb8a8 | HTTP requests with unusual HTTP headers or URI path (signature #52). | N/A             | block      |       |
| ...5c344623 | HTTP requests from uncommon clients                                  | N/A             | block      |       |
| ...6363bb1b | HTTP requests with unusual HTTP headers or URI path (signature #48). | N/A             | block      |       |
| ...c1fbd175 | HTTP requests trying to impersonate browsers (pattern #4).           | N/A             | block      |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-10-09-emergency/","name":"2023-10-09 - Emergency"}}]}
```

---

---
title: 2023-10-11
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-10-11

| Rule ID     | Description                                                          | Previous Action | New Action | Notes                                                                              |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | ---------------------------------------------------------------------------------- |
| ...35675e08 | HTTP requests with unusual HTTP headers or URI path (signature #24). | block           | block      | This rule can cause rare false positives with custom apps sending invalid headers. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-10-11/","name":"2023-10-11"}}]}
```

---

---
title: 2023-10-19
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-10-19

| Rule ID     | Description                                                          | Previous Action | New Action    | Notes                                                               |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------- | ------------------------------------------------------------------- |
| ...61bc58d5 | HTTP requests with unusual HTTP headers or URI path (signature #55). | ddos\_dynamic   | ddos\_dynamic | Requests will be challenged by default, larger attacks are blocked. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-10-19/","name":"2023-10-19"}}]}
```

---

---
title: 2023-11-10 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-11-10 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action    | Notes                                              |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------- | -------------------------------------------------- |
| ...7d0f1e5f | HTTP requests from known botnet (signature #72).                     | N/A             | block         |                                                    |
| ...94547a95 | HTTP requests with unusual HTTP headers or URI path (signature #59). | N/A             | ddos\_dynamic |                                                    |
| ...e269dfd6 | HTTP requests with unusual HTTP headers or URI path (signature #56). | log             | block         | Enable filter early to mitigate widespread impact. |
| ...f35a42a0 | HTTP requests with unusual HTTP headers or URI path (signature #57). | log             | block         | Enable filter early to mitigate widespread impact. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-11-10-emergency/","name":"2023-11-10 - Emergency"}}]}
```

---

---
title: 2023-11-13 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-11-13 - Emergency

| Rule ID     | Description                                      | Previous Action | New Action    | Notes                                      |
| ----------- | ------------------------------------------------ | --------------- | ------------- | ------------------------------------------ |
| ...22807318 | HTTP requests from known botnets.                | ddos\_dynamic   | ddos\_dynamic | Improve this filter to catch more attacks. |
| ...6fe7a312 | HTTP requests from known botnet (signature #70). | block           | block         |                                            |
| ...7c7a2f25 | HTTP requests from known botnet (signature #74). | N/A             | block         |                                            |
| ...d2f294d7 | HTTP requests trying to impersonate browsers.    | ddos\_dynamic   | ddos\_dynamic |                                            |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-11-13-emergency/","name":"2023-11-13 - Emergency"}}]}
```

---

---
title: 2023-11-22
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-11-22

| Rule ID     | Description                                                          | Previous Action | New Action | Notes |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | ----- |
| ...254da96a | HTTP requests with unusual HTTP headers or URI path (signature #58). | log             | block      |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-11-22/","name":"2023-11-22"}}]}
```

---

---
title: 2023-11-29
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-11-29

| Rule ID     | Description                                                          | Previous Action | New Action    | Notes                           |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------- | ------------------------------- |
| ...8ed59b32 | HTTP requests with unusual HTTP headers or URI path (signature #61). | ddos\_dynamic   | ddos\_dynamic | Rename rule to avoid confusion. |
| ...61e8d513 | Global L7 WordPress attack mitigations (Deprecated)                  | ddos\_dynamic   | ddos\_dynamic | Mark rule as deprecated.        |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-11-29/","name":"2023-11-29"}}]}
```

---

---
title: 2023-12-08 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-12-08 - Emergency

| Rule ID     | Description                                      | Previous Action | New Action | Notes                                                                 |
| ----------- | ------------------------------------------------ | --------------- | ---------- | --------------------------------------------------------------------- |
| ...6fe7a312 | HTTP requests from known botnet (signature #70). | block           | block      | Updated the rule to avoid false positives in some rare circumstances. |
| ...e7a37252 | HTTP requests from known botnet (signature #75). | N/A             | block      |                                                                       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-12-08-emergency/","name":"2023-12-08 - Emergency"}}]}
```

---

---
title: 2023-12-14 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-12-14 - Emergency

| Rule ID     | Description                                      | Previous Action | New Action | Notes                                                       |
| ----------- | ------------------------------------------------ | --------------- | ---------- | ----------------------------------------------------------- |
| ...6fe7a312 | HTTP requests from known botnet (signature #70). | block           | block      | Tweak the rule to avoid false positives in some rare cases. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-12-14-emergency/","name":"2023-12-14 - Emergency"}}]}
```

---

---
title: 2023-12-19 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2023-12-19 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action    | Notes                                                             |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------- | ----------------------------------------------------------------- |
| ...1fc1e601 | HTTP requests with unusual HTTP headers or URI path (signature #31). | block           | block         | Add more characteristics to the unusual HTTP headers or URI path. |
| ...22807318 | HTTP requests from known botnets.                                    | log             | ddos\_dynamic | Extend the rule to catch more attacks.                            |
| ...d2f294d7 | HTTP requests trying to impersonate browsers.                        | ddos\_dynamic   | ddos\_dynamic | Change the rule to catch more attacks.                            |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2023-12-19-emergency/","name":"2023-12-19 - Emergency"}}]}
```

---

---
title: 2024-01-05
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2024-01-05

| Rule ID     | Description                                                         | Previous Action | New Action | Notes                                                  |
| ----------- | ------------------------------------------------------------------- | --------------- | ---------- | ------------------------------------------------------ |
| ...2de94fb2 | HTTP requests with unusual HTTP headers or URI path (signature #3). | block           | block      | Fine-tune the characteristics of the unusual requests. |
| ...177059f1 | HTTP requests from known botnet (signature #31).                    | block           | N/A        | Removed due to false positives.                        |
| ...6fe7a312 | HTTP requests from known botnet (signature #70).                    | block           | N/A        | Removed due to false positives.                        |
| ...82c0ed5f | HTTP requests from known botnet (signature #77).                    | N/A             | block      |                                                        |
| ...e4f3ea4d | HTTP requests from known botnet (signature #76).                    | N/A             | block      |                                                        |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2024-01-05/","name":"2024-01-05"}}]}
```

---

---
title: 2024-01-23
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2024-01-23

| Rule ID     | Description                                                          | Previous Action | New Action | Notes                                                             |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | ----------------------------------------------------------------- |
| ...1fc1e601 | HTTP requests with unusual HTTP headers or URI path (signature #31). | block           | block      | Add more characteristics to the unusual HTTP headers or URI path. |
| ...2de94fb2 | HTTP requests with unusual HTTP headers or URI path (signature #3).  | ddos\_dynamic   | block      | Expand rule scope to catch more attacks.                          |
| ...2f8d9a4f | HTTP requests from known botnet (signature #78).                     | N/A             | block      |                                                                   |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2024-01-23/","name":"2024-01-23"}}]}
```

---

---
title: 2024-01-25
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2024-01-25

| Rule ID     | Description                                                          | Previous Action | New Action | Notes                                                             |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | ----------------------------------------------------------------- |
| ...1fc1e601 | HTTP requests with unusual HTTP headers or URI path (signature #31). | block           | block      | Add more characteristics to the unusual HTTP headers or URI path. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2024-01-25/","name":"2024-01-25"}}]}
```

---

---
title: 2024-01-26 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2024-01-26 - Emergency

| Rule ID     | Description                                                          | Previous Action    | New Action         | Notes                                                              |
| ----------- | -------------------------------------------------------------------- | ------------------ | ------------------ | ------------------------------------------------------------------ |
| ...3ad719cd | HTTP requests from known botnet (signature #79).                     | N/A                | ddos\_dynamic      |                                                                    |
| ...61bc58d5 | HTTP requests with unusual HTTP headers or URI path (signature #55). | managed\_challenge | managed\_challenge | Expanded the scope of the rule to catch attacks more consistently. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2024-01-26-emergency/","name":"2024-01-26 - Emergency"}}]}
```

---

---
title: 2024-02-05 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2024-02-05 - Emergency

| Rule ID     | Description                       | Previous Action | New Action    | Notes                                  |
| ----------- | --------------------------------- | --------------- | ------------- | -------------------------------------- |
| ...22807318 | HTTP requests from known botnets. | ddos\_dynamic   | ddos\_dynamic | Extend the rule to catch more attacks. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2024-02-05-emergency/","name":"2024-02-05 - Emergency"}}]}
```

---

---
title: 2024-02-06 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2024-02-06 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action    | Notes                                                           |
| ----------- | -------------------------------------------------------------------- | --------------- | ------------- | --------------------------------------------------------------- |
| ...1fc1e601 | HTTP requests with unusual HTTP headers or URI path (signature #31). | block           | block         | Modify characteristics of the unusual HTTP headers or URI path. |
| ...3a679c52 | Requests coming from known bad sources.                              | N/A             | ddos\_dynamic |                                                                 |
| ...3ad719cd | HTTP requests from known botnet (signature #79).                     | ddos\_dynamic   | ddos\_dynamic | Expand the scope of the rule to match more attacks.             |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2024-02-06-emergency/","name":"2024-02-06 - Emergency"}}]}
```

---

---
title: 2024-02-08 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2024-02-08 - Emergency

| Rule ID     | Description                             | Previous Action | New Action         | Notes                                     |
| ----------- | --------------------------------------- | --------------- | ------------------ | ----------------------------------------- |
| ...3a679c52 | Requests coming from known bad sources. | ddos\_dynamic   | managed\_challenge | Expand the rule to mitigate on all zones. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2024-02-08-emergency/","name":"2024-02-08 - Emergency"}}]}
```

---

---
title: 2024-02-12
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# 2024-02-12

| Rule ID     | Description                                                          | Previous Action | New Action | Notes |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | ----- |
| ...c47bdca6 | HTTP requests with unusual HTTP headers or URI path (signature #62). | N/A             | block      |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2024-02-12/","name":"2024-02-12"}}]}
```

---

---
title: 2024-02-19
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2024-02-19

| Rule ID     | Description                                      | Previous Action | New Action    | Notes                                        |
| ----------- | ------------------------------------------------ | --------------- | ------------- | -------------------------------------------- |
| ...0fbfd5ae | HTTP requests from known botnet (signature #32). | block           | ddos\_dynamic |                                              |
| ...22807318 | HTTP requests from known botnets.                | ddos\_dynamic   | ddos\_dynamic | Expand rule logic to catch more attacks.     |
| ...3ad719cd | HTTP requests from known botnet (signature #79). | ddos\_dynamic   | ddos\_dynamic | Expand the rule scope to catch more attacks. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2024-02-19/","name":"2024-02-19"}}]}
```

---

---
title: 2024-02-26 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2024-02-26 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action | Notes                                                  |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | ------------------------------------------------------ |
| ...6831bff1 | HTTP requests with unusual HTTP headers or URI path (signature #35). | block           | block      | Extend the rule to catch attacks more comprehensively. |
| ...e269dfd6 | HTTP requests with unusual HTTP headers or URI path (signature #56). | block           | block      | Extend the rule to catch attacks more comprehensively. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2024-02-26-emergency/","name":"2024-02-26 - Emergency"}}]}
```

---

---
title: 2024-02-27
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2024-02-27

| Rule ID     | Description                                                                                                    | Previous Action | New Action    | Notes                                                |
| ----------- | -------------------------------------------------------------------------------------------------------------- | --------------- | ------------- | ---------------------------------------------------- |
| ...0c9175b8 | HTTP requests from known botnet (signature #47).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...0fb54442 | HTTP requests with unusual HTTP headers or URI path (signature #49).                                           | block           | N/A           | Rule removed due to inactivity.                      |
| ...1b60260f | HTTP requests from known botnet (signature #45).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...21e99dcf | HTTP requests from known botnet (signature #58).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...3f7952da | HTTP requests from known botnet (signature #21).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...5a158253 | HTTP requests from known botnet (signature #27).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...5f1469cb | HTTP requests with unusual HTTP headers or URI path (signature #28).                                           | block           | N/A           | Rule removed due to inactivity.                      |
| ...71cb9bea | HTTP requests from known botnet (signature #39).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...72d115bd | HTTP requests from known botnet (signature #23).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...8586375f | HTTP requests with unusual HTTP headers or URI path (signature #22).                                           | block           | N/A           | Rule removed due to inactivity.                      |
| ...8857b788 | HTTP requests from known botnet (signature #30).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...8bf63869 | HTTP requests from known botnet (signature #50).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...9630955e | HTTP requests from known botnet (signature #64).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...9641efe0 | HTTP requests with unusual HTTP headers or URI path (signature #29).                                           | block           | N/A           | Rule removed due to inactivity.                      |
| ...aa03a345 | HTTP requests from known botnet (signature #68).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...b60b2bc0 | HTTP requests from known botnet (signature #28).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...bbf0073e | HTTP requests from known botnet (signature #25).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...c5f479f0 | HTTP requests from known botnet (signature #62).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...c92eba7c | HTTP requests from known botnet (signature #65).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...dea7a346 | HTTP requests from known botnet (signature #35).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...e4fe8e55 | Adaptive DDoS Protection based on User-Agents (Available only to Enterprise zones with Advanced DDoS service). | ddos\_dynamic   | ddos\_dynamic | Mitigate attacks by default instead of only logging. |
| ...ea99fbb6 | HTTP requests from known botnet (signature #46).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...f6120981 | HTTP requests from known botnet (signature #20).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...f9da654a | HTTP requests from known botnet (signature #26).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...fd5045ff | HTTP requests from known botnet (signature #55).                                                               | block           | N/A           | Rule removed due to inactivity.                      |
| ...fd551e2b | HTTP requests from known botnet (signature #41).                                                               | block           | N/A           | Rule removed due to inactivity.                      |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2024-02-27/","name":"2024-02-27"}}]}
```

---

---
title: 2024-04-02
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2024-04-02

| Rule ID     | Description                                   | Previous Action | New Action    | Notes                                                        |
| ----------- | --------------------------------------------- | --------------- | ------------- | ------------------------------------------------------------ |
| ...d2f294d7 | HTTP requests trying to impersonate browsers. | ddos\_dynamic   | ddos\_dynamic | Update the rule to match to block attacks more consistently. |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2024-04-02/","name":"2024-04-02"}}]}
```

---

---
title: 2024-04-04 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2024-04-04 - Emergency

| Rule ID     | Description                                      | Previous Action | New Action | Notes |
| ----------- | ------------------------------------------------ | --------------- | ---------- | ----- |
| ...177059f1 | HTTP requests from known botnet (signature #31). | log             | N/A        |       |
| ...7b231fb2 | HTTP requests from known botnet (signature #81). | N/A             | block      |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2024-04-04-emergency/","name":"2024-04-04 - Emergency"}}]}
```

---

---
title: 2024-04-16 - Emergency
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2024-04-16 - Emergency

| Rule ID     | Description                                                          | Previous Action | New Action | Notes |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | ----- |
| ...05ad9070 | HTTP requests with unusual HTTP headers or URI path (signature #64). | N/A             | block      |       |
| ...890b8f4e | HTTP requests with unusual HTTP headers or URI path (signature #65). | N/A             | block      |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2024-04-16-emergency/","name":"2024-04-16 - Emergency"}}]}
```

---

---
title: 2024-04-19
description: HTTP DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2024-04-19

| Rule ID     | Description                                                          | Previous Action | New Action | Notes |
| ----------- | -------------------------------------------------------------------- | --------------- | ---------- | ----- |
| ...154b29a0 | HTTP requests with unusual HTTP headers or URI path (signature #66). | N/A             | block      |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/2024-04-19/","name":"2024-04-19"}}]}
```

---

---
title: Scheduled changes
description: Upcoming scheduled rule changes for the HTTP DDoS managed ruleset.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Scheduled changes

| Announcement Date | Change Date | Rule ID | Description | Previous Action | New Action | Notes |
| ----------------- | ----------- | ------- | ----------- | --------------- | ---------- | ----- |
| N/A               | N/A         | N/A     | N/A         | N/A             | N/A        | N/A   |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/http/","name":"HTTP DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/http/scheduled-changes/","name":"Scheduled changes"}}]}
```

---

---
title: Network-layer DDoS managed ruleset
description: Changelog of rule updates for the Network-layer DDoS managed ruleset.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Network-layer DDoS managed ruleset

This section contains past and upcoming changes to the [Network-layer DDoS Attack Protection managed ruleset](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/).

Note

The Network-layer DDoS Attack Protection managed ruleset protects Cloudflare customers on all plans. However, only [Magic transit](https://developers.cloudflare.com/magic-transit/) and [Spectrum](https://developers.cloudflare.com/spectrum/) customers on an Enterprise plan can customize the managed ruleset.

[ View scheduled changes ](https://developers.cloudflare.com/ddos-protection/change-log/network/scheduled-changes/) [ Subscribe to RSS ](https://developers.cloudflare.com/ddos-protection/change-log/network/index.xml) 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/network/","name":"Network-layer DDoS managed ruleset"}}]}
```

---

---
title: 2022-04-12
description: Network-layer DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2022-04-12

| Rule ID     | Description                                                       | Previous Action | New Action    | Notes |
| ----------- | ----------------------------------------------------------------- | --------------- | ------------- | ----- |
| ...89e250ce | IPv4 GRE encapsulated IP or PPP (Inner protocol 0x0800 or 0x880B) | ddos\_dynamic   | ddos\_dynamic |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/network/","name":"Network-layer DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/network/2022-04-12/","name":"2022-04-12"}}]}
```

---

---
title: 2022-09-16
description: Network-layer DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2022-09-16

| Rule ID     | Description                                                                          | Previous Action | New Action | Notes |
| ----------- | ------------------------------------------------------------------------------------ | --------------- | ---------- | ----- |
| ...11456494 | IPv6 GRE miscellaneous inner protocols (Inner protocols other than 0x0800 or 0x880B) | block           | N/A        |       |
| ...800534de | IPv6 GRE encapsulated IP or PPP (Inner protocol 0x0800 or 0x880B)                    | ddos\_dynamic   | N/A        |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/network/","name":"Network-layer DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/network/2022-09-16/","name":"2022-09-16"}}]}
```

---

---
title: 2022-09-21
description: Network-layer DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2022-09-21

| Rule ID     | Description                                                                                | Previous Action | New Action | Notes                                                     |
| ----------- | ------------------------------------------------------------------------------------------ | --------------- | ---------- | --------------------------------------------------------- |
| ...58e4914a | Adaptive DDoS Protection for UDP (Available only to Enterprise accounts).                  | log             | log        | Update UDP profiling rule tag and threshold               |
| ...76d5e15c | Adaptive DDoS Protection for Other IPv6 Protocols (Available only to Enterprise accounts). | log             | log        | Update other IPv6 protos profiling rule tag and threshold |
| ...8de83ef6 | Adaptive DDoS Protection for IPv6 GRE (Available only to Enterprise accounts).             | log             | log        | Update IPv6 GRE profiling rule tag and threshold          |
| ...938e978c | Adaptive DDoS Protection for IPv6 ESP (Available only to Enterprise accounts).             | log             | log        | Update IPv6 ESP profiling rule tag and threshold          |
| ...9c173480 | Adaptive DDoS Protection for ICMP (Available only to Enterprise accounts).                 | log             | log        | Update ICMP profiling rule tag and threshold              |
| ...ad8078b8 | Adaptive DDoS Protection for IPv4 GRE (Available only to Enterprise accounts).             | log             | log        | Update IPv4 GRE profiling rule tag and threshold          |
| ...ae3f5e4e | Adaptive DDoS Protection for ICMPv6 (Available only to Enterprise accounts).               | log             | log        | Update ICMPv6 profiling rule tag and threshold            |
| ...c7dc52df | Adaptive DDoS Protection for Other IPv4 Protocols (Available only to Enterprise accounts). | log             | log        | Update other IPv4 protos profiling rule tag and threshold |
| ...e4e7541c | Adaptive DDoS Protection for IPv4 ESP (Available only to Enterprise accounts).             | log             | log        | Update IPv4 ESP profiling rule tag and threshold          |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/network/","name":"Network-layer DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/network/2022-09-21/","name":"2022-09-21"}}]}
```

---

---
title: 2022-10-06
description: Network-layer DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2022-10-06

| Rule ID     | Description                                                                                | Previous Action | New Action | Notes |
| ----------- | ------------------------------------------------------------------------------------------ | --------------- | ---------- | ----- |
| ...34228119 | IPv4 UDP SIP traffic                                                                       | log             | N/A        |       |
| ...58e4914a | Adaptive DDoS Protection for UDP (Available only to Enterprise accounts).                  | log             | N/A        |       |
| ...76d5e15c | Adaptive DDoS Protection for Other IPv6 Protocols (Available only to Enterprise accounts). | log             | N/A        |       |
| ...8de83ef6 | Adaptive DDoS Protection for IPv6 GRE (Available only to Enterprise accounts).             | log             | N/A        |       |
| ...938e978c | Adaptive DDoS Protection for IPv6 ESP (Available only to Enterprise accounts).             | log             | N/A        |       |
| ...9c173480 | Adaptive DDoS Protection for ICMP (Available only to Enterprise accounts).                 | log             | N/A        |       |
| ...ad8078b8 | Adaptive DDoS Protection for IPv4 GRE (Available only to Enterprise accounts).             | log             | N/A        |       |
| ...ae3f5e4e | Adaptive DDoS Protection for ICMPv6 (Available only to Enterprise accounts).               | log             | N/A        |       |
| ...c7dc52df | Adaptive DDoS Protection for Other IPv4 Protocols (Available only to Enterprise accounts). | log             | N/A        |       |
| ...e4e7541c | Adaptive DDoS Protection for IPv4 ESP (Available only to Enterprise accounts).             | log             | N/A        |       |
| ...ea9e05c3 | IPv6 UDP SIP traffic                                                                       | log             | N/A        |       |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/network/","name":"Network-layer DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/network/2022-10-06/","name":"2022-10-06"}}]}
```

---

---
title: 2022-10-24
description: Network-layer DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2022-10-24

| Rule ID     | Description                                                                    | Previous Action | New Action | Notes                                      |
| ----------- | ------------------------------------------------------------------------------ | --------------- | ---------- | ------------------------------------------ |
| ...e4e7541c | Adaptive DDoS Protection for IPv4 ESP (Available only to Enterprise accounts). | log             | log        | Lower sensitivity to avoid false positives |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/network/","name":"Network-layer DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/network/2022-10-24/","name":"2022-10-24"}}]}
```

---

---
title: 2022-12-02
description: Network-layer DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2022-12-02

| Rule ID     | Description                                                                                | Previous Action | New Action | Notes                                      |
| ----------- | ------------------------------------------------------------------------------------------ | --------------- | ---------- | ------------------------------------------ |
| ...58e4914a | Adaptive DDoS Protection for UDP (Available only to Enterprise accounts).                  | log             | log        | Lower sensitivity to avoid false positives |
| ...76d5e15c | Adaptive DDoS Protection for Other IPv6 Protocols (Available only to Enterprise accounts). | log             | log        | Lower sensitivity to avoid false positives |
| ...8de83ef6 | Adaptive DDoS Protection for IPv6 GRE (Available only to Enterprise accounts).             | log             | log        | Lower sensitivity to avoid false positives |
| ...938e978c | Adaptive DDoS Protection for IPv6 ESP (Available only to Enterprise accounts).             | log             | log        | Lower sensitivity to avoid false positives |
| ...9c173480 | Adaptive DDoS Protection for ICMP (Available only to Enterprise accounts).                 | log             | log        | Lower sensitivity to avoid false positives |
| ...ad8078b8 | Adaptive DDoS Protection for IPv4 GRE (Available only to Enterprise accounts).             | log             | log        | Lower sensitivity to avoid false positives |
| ...ae3f5e4e | Adaptive DDoS Protection for ICMPv6 (Available only to Enterprise accounts).               | log             | log        | Lower sensitivity to avoid false positives |
| ...c7dc52df | Adaptive DDoS Protection for Other IPv4 Protocols (Available only to Enterprise accounts). | log             | log        | Lower sensitivity to avoid false positives |
| ...e4e7541c | Adaptive DDoS Protection for IPv4 ESP (Available only to Enterprise accounts).             | log             | log        | Lower sensitivity to avoid false positives |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/network/","name":"Network-layer DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/network/2022-12-02/","name":"2022-12-02"}}]}
```

---

---
title: 2023-04-17
description: Network-layer DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2023-04-17

Previously, only a subset of rules were exposed publicly. In rare situations, these rules can cause false positives. When this happens, you can customize their behavior using overrides.

Besides these rules, the DDoS managed rules contain other rules that do not cause issues. Until now, these rules were not shown in the dashboard or referenced in the documentation.

Cloudflare now shows all rules in the dashboard, including these high-confidence rules. This means that packets matching these rules will now have the correct rule identifier. The newly published rules are read-only and you cannot disable them.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/network/","name":"Network-layer DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/network/2023-04-17/","name":"2023-04-17"}}]}
```

---

---
title: 2023-07-31
description: Network-layer DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2023-07-31

| Rule ID     | Description                                                                              | Previous Action | New Action | Notes                                     |
| ----------- | ---------------------------------------------------------------------------------------- | --------------- | ---------- | ----------------------------------------- |
| ...aa772b5c | Adaptive DDoS Protection for Location-Based UDP (Available only to Enterprise accounts). | N/A             | log        | Enable UDP geolocation Adaptive DDoS rule |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/network/","name":"Network-layer DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/network/2023-07-31/","name":"2023-07-31"}}]}
```

---

---
title: 2024-03-12
description: Network-layer DDoS managed ruleset rule changes for this release.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# 2024-03-12

| Rule ID     | Description                                                                                 | Previous Action | New Action | Notes                                                                                                      |
| ----------- | ------------------------------------------------------------------------------------------- | --------------- | ---------- | ---------------------------------------------------------------------------------------------------------- |
| ...85fa2e98 | Adaptive DDoS Protection for UDP Destination Ports (Available only to Enterprise accounts). | N/A             | log        | Enable rule that uses a customer's UDP destination port profile to mitigate traffic (log mode by default). |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/network/","name":"Network-layer DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/network/2024-03-12/","name":"2024-03-12"}}]}
```

---

---
title: Scheduled changes
description: Upcoming scheduled rule changes for the Network-layer DDoS managed ruleset.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Scheduled changes

| Announcement Date | Change Date | Rule ID | Description | Previous Action | New Action | Notes |
| ----------------- | ----------- | ------- | ----------- | --------------- | ---------- | ----- |
| N/A               | N/A         | N/A     | N/A         | N/A             | N/A        | N/A   |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/change-log/","name":"Changelog"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/change-log/network/","name":"Network-layer DDoS managed ruleset"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/change-log/network/scheduled-changes/","name":"Scheduled changes"}}]}
```

---

---
title: Advanced DNS Protection
description: Configure Advanced DNS Protection rules and settings using the Cloudflare API.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Advanced DNS Protection

Use the [Cloudflare API](https://developers.cloudflare.com/api/) to configure Advanced DNS Protection via API.

For examples of API calls, refer to [Common API calls](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/dns-protection/examples/).

## Endpoints

To obtain the complete endpoint, append the Advanced DNS Protection API endpoints listed below to the Cloudflare API base URL:

```

https://api.cloudflare.com/client/v4


```

The `{account_id}` argument is the [account ID](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/) (a hexadecimal string). You can find this value in the Cloudflare dashboard.

The following table summarizes the available operations.

| Operation                       | Verb + Endpoint                                                                                                                                                           |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| List DNS protection rules       | GET accounts/{account\_id}/magic/advanced\_dns\_protection/configs/dns\_protection/rulesFetches all DNS protection rules in the account.                                  |
| Add a DNS protection rule       | POST accounts/{account\_id}/magic/advanced\_dns\_protection/configs/dns\_protection/rulesAdds a DNS protection rule to the account.                                       |
| Get a DNS protection rule       | GET accounts/{account\_id}/magic/advanced\_dns\_protection/configs/dns\_protection/rules/{rule\_id}Fetches the details of an existing DNS protection rule in the account. |
| Update a DNS protection rule    | PATCH accounts/{account\_id}/magic/advanced\_dns\_protection/configs/dns\_protection/rules/{rule\_id}Updates an existing DNS protection rule in the account.              |
| Delete a DNS protection rule    | DELETE accounts/{account\_id}/magic/advanced\_dns\_protection/configs/dns\_protection/rules/{rule\_id}Deletes an existing DNS protection rule from the account.           |
| Delete all DNS protection rules | DELETE accounts/{account\_id}/magic/advanced\_dns\_protection/configs/dns\_protection/rulesDeletes all existing DNS protection rules from the account.                    |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/","name":"API configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/dns-protection/","name":"Advanced DNS Protection"}}]}
```

---

---
title: Common API calls
description: Example API requests for managing Advanced DNS Protection rules and settings.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Common API calls

The following sections contain example requests for common API calls. For a list of available API endpoints, refer to [Endpoints](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/dns-protection/#endpoints).

## Get all DNS protection rules

The following example retrieves the currently configured rules for Advanced DNS Protection.

Request

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/advanced_dns_protection/configs/dns_protection/rules" \

--header "Authorization: Bearer <API_TOKEN>"


```

```

---

{

  "result": [

    {

      "id": "<RULE_ID>",

      "scope": "<SCOPE>",

      "name": "<NAME>",

      "mode": "<MODE>",

      "profile_sensitivity": "<SENSITIVITY>",

      "rate_sensitivity": "<RATE>",

      "burst_sensitivity": "<BURST>",

      "created_on": "2023-10-01T13:10:38.762503+01:00",

      "modified_on": "2023-10-01T13:10:38.762503+01:00",

      }

    ],

  "success": true,

  "errors": [],

  "messages": []

}


```

### Create DNS protection rule

The following example creates an Advanced DNS Protection rule with a global scope.

Request

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/advanced_dns_protection/configs/dns_protection/rules" \

--header "Authorization: Bearer <API_TOKEN>" \

--data '{

  "scope": "global",

  "name": "global",

  "mode": "<MODE>",

  "rate_sensitivity": "<RATE>",

  "burst_sensitivity": "<BURST>",

  "profile_sensitivity": "<SENSITIVITY>"

}'


```

```

{

  "result": {

    "id": "<RULE_ID>",

    "scope": "global",

    "name": "global",

    "mode": "<MODE>",

    "rate_sensitivity": "<RATE>",

    "burst_sensitivity": "<BURST>",

    "profile_sensitivity": "<SENSITIVITY>",

    "created_on": "2023-10-01T13:10:38.762503+01:00",

    "modified_on": "2023-10-01T13:10:38.762503+01:00",

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

Refer to [JSON objects](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/dns-protection/json-objects/) for more information on the fields in the JSON body.

### Update DNS protection rule

The following example updates an existing DNS protection rule with ID `{rule_id}`.

The request body can contain only the fields you want to update (from `mode`, `profile_sensitivity`, `rate_sensitivity`, and `burst_sensitivity`).

Request

```

curl --request PATCH \

"https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/advanced_dns_protection/configs/dns_protection/rules/{rule_id}" \

--header "Authorization: Bearer <API_TOKEN>" \

--data '{

  "mode": "<NEW_MODE>",

  "profile_sensitivity": "<NEW_SENSITIVITY>",

  "rate_sensitivity": "<NEW_RATE>",

  "burst_sensitivity": "<NEW_BURST>"

}'


```

```

{

  "result": {

    "id": "<RULE_ID>",

    "scope": "<SCOPE>",

    "name": "<NAME>",

    "mode": "<NEW_MODE>",

    "profile_sensitivity": "<NEW_SENSITIVITY>",

    "rate_sensitivity": "<NEW_RATE>",

    "burst_sensitivity": "<NEW_BURST>",

    "created_on": "2023-10-01T13:10:38.762503+01:00",

    "modified_on": "2023-10-01T13:10:38.762503+01:00",

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

Refer to [JSON objects](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/dns-protection/json-objects/) for more information on the fields in the JSON body.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/","name":"API configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/dns-protection/","name":"Advanced DNS Protection"}},{"@type":"ListItem","position":6,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/dns-protection/examples/","name":"Common API calls"}}]}
```

---

---
title: JSON objects
description: JSON object structure for Advanced DNS Protection API requests and responses.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# JSON objects

# JSON object

This page contains an example of the DNS protection rule JSON object used in the API.

```

{

  "id": "31c70c65-9f81-4669-94ed-1e1e041e7b06",

  "scope": "region",

  "name": "WEUR",

  "mode": "monitoring",

  "profile_sensitivity": "medium",

  "rate_sensitivity": "medium",

  "burst_sensitivity": "medium",

  "created_on": "2023-10-01T13:10:38.762503+01:00",

  "modified_on": "2023-10-01T13:10:38.762503+01:00"

}


```

The `scope` field value must be one of `global`, `region`, or `datacenter`. You must provide a region code (or data center code) in the `name` field when specifying a `region` (or `datacenter`) scope.

The `mode` value must be one of `enabled`, `disabled`, or `monitoring`.

The `profile_sensitivity` field value must be one of `low` (default), `medium`, `high`, or `very_high`.

The `rate_sensitivity` and `burst_sensitivity` field values must be one of `low`, `medium`, or `high`.

For more information on the rule settings, refer to [Rule settings](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#rule-settings).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/","name":"API configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/dns-protection/","name":"Advanced DNS Protection"}},{"@type":"ListItem","position":6,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/dns-protection/json-objects/","name":"JSON objects"}}]}
```

---

---
title: Programmable Flow Protection
description: Configure Programmable Flow Protection programs and rules using the Cloudflare API.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Programmable Flow Protection

Use the [Cloudflare API](https://developers.cloudflare.com/api/) to configure Programmable Flow Protection.

For examples of API calls, refer to [Common API calls](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/programmable-flow-protection/examples/).

## Endpoints

To obtain the complete endpoint, append the Programmable Flow Protection API endpoints listed below to the Cloudflare API base URL:

```

https://api.cloudflare.com/client/v4


```

The `{account_id}` argument is the [account ID](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/) (a hexadecimal string). You can find this value in the Cloudflare dashboard.

The tables in the following sections summarize the available operations.

### Program operations

| Operation           | Method and endpoint / Description                                                                                                                 |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| List programs       | GET accounts/{account\_id}/magic/programmable\_flow\_protection/configs/programsFetches all Programmable Flow Protection programs in the account. |
| Upload a program    | POST accounts/{account\_id}/magic/programmable\_flow\_protection/configs/programsUploads a new program to the account.                            |
| Get a program       | GET accounts/{account\_id}/magic/programmable\_flow\_protection/configs/programs/{program\_id}Fetches the details of an existing program.         |
| Update a program    | PATCH accounts/{account\_id}/magic/programmable\_flow\_protection/configs/programs/{program\_id}Updates an existing program.                      |
| Delete a program    | DELETE accounts/{account\_id}/magic/programmable\_flow\_protection/configs/programs/{program\_id}Deletes an existing program from the account.    |
| Delete all programs | DELETE accounts/{account\_id}/magic/programmable\_flow\_protection/configs/programsDeletes all existing programs from the account.                |

### Rule operations

| Operation        | Method and endpoint / Description                                                                                                           |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| List rules       | GET accounts/{account\_id}/magic/programmable\_flow\_protection/configs/rulesFetches all Programmable Flow Protection rules in the account. |
| Create a rule    | POST accounts/{account\_id}/magic/programmable\_flow\_protection/configs/rulesCreates a new rule in the account.                            |
| Get a rule       | GET accounts/{account\_id}/magic/programmable\_flow\_protection/configs/rules/{rule\_id}Fetches the details of an existing rule.            |
| Update a rule    | PATCH accounts/{account\_id}/magic/programmable\_flow\_protection/configs/rules/{rule\_id}Updates an existing rule in the account.          |
| Delete a rule    | DELETE accounts/{account\_id}/magic/programmable\_flow\_protection/configs/rules/{rule\_id}Deletes an existing rule from the account.       |
| Delete all rules | DELETE accounts/{account\_id}/magic/programmable\_flow\_protection/configs/rulesDeletes all existing rules from the account.                |

### Debug operations

| Operation       | Method and endpoint / Description                                                                                                                                                           |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Debug with PCAP | POST accounts/{account\_id}/magic/programmable\_flow\_protection/configs/programs/{program\_id}/pcapRuns a program against a PCAP file and returns an annotated PCAP with program verdicts. |

## Pagination

The API operations that return a list of items use pagination. For more information on the available pagination query parameters, refer to [Pagination](https://developers.cloudflare.com/fundamentals/api/how-to/make-api-calls/#pagination).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/","name":"API configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/programmable-flow-protection/","name":"Programmable Flow Protection"}}]}
```

---

---
title: Common API calls
description: Example API requests for managing Programmable Flow Protection programs and rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Common API calls

The following sections contain example requests for common API calls. For a list of available API endpoints, refer to [Endpoints](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/programmable-flow-protection/#endpoints).

## List all programs

This example fetches all Programmable Flow Protection programs in the account.

Request

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/programmable_flow_protection/configs/programs" \

--header "Authorization: Bearer <API_TOKEN>"


```

Response

```

{

  "result": [

    {

      "id": "<PROGRAM_ID>",

      "name": "rate-limiter",

      "status": "success",

      "created_on": "<TIMESTAMP>",

      "modified_on": "<TIMESTAMP>"

    }

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

## Upload a program

This example uploads a new eBPF program written in C. The program source code is sent as the request body with `Content-Type: text/plain`.

Request

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/programmable_flow_protection/configs/programs" \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: text/plain" \

--data-binary "@/path/to/program.c"


```

Response

```

{

  "result": {

    "id": "<PROGRAM_ID>",

    "name": "program",

    "status": "success",

    "created_on": "<TIMESTAMP>",

    "modified_on": "<TIMESTAMP>"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

If the program fails compilation or verification, the API returns a detailed error message:

Example error response

```

{

  "result": null,

  "success": false,

  "errors": [

    {

      "code": 1001,

      "message": "Program verification failed: invalid memory access at line 42"

    }

  ],

  "messages": []

}


```

## Update a program

This example updates an existing program with new source code. You can update a program even if it is currently in use by one or more rules. If the new program fails compilation or verification, the update fails and the existing program remains active.

Request

```

curl --request PATCH \

"https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/programmable_flow_protection/configs/programs/{program_id}" \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: text/plain" \

--data-binary "@/path/to/updated-program.c"


```

Response

```

{

  "result": {

    "id": "<PROGRAM_ID>",

    "name": "program",

    "status": "success",

    "created_on": "<TIMESTAMP>",

    "modified_on": "<TIMESTAMP>"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

## Delete a program

This example deletes a program. You cannot delete a program that is currently referenced by an active rule.

Request

```

curl --request DELETE \

"https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/programmable_flow_protection/configs/programs/{program_id}" \

--header "Authorization: Bearer <API_TOKEN>"


```

Response

```

{

  "result": null,

  "success": true,

  "errors": [],

  "messages": []

}


```

## List all rules

This example fetches all Programmable Flow Protection rules in the account.

Request

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/programmable_flow_protection/configs/rules" \

--header "Authorization: Bearer <API_TOKEN>"


```

Response

```

{

  "result": [

    {

      "id": "<RULE_ID>",

      "program_id": "<PROGRAM_ID>",

      "scope": "global",

      "name": "global",

      "mode": "enabled",

      "expression": "",

      "created_on": "<TIMESTAMP>",

      "modified_on": "<TIMESTAMP>"

    }

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

## Create a rule

This example creates a Programmable Flow Protection rule with a global scope in monitoring mode.

Request

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/programmable_flow_protection/configs/rules" \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "program_id": "<PROGRAM_ID>",

  "scope": "global",

  "name": "global",

  "mode": "monitoring"

}'


```

Response

```

{

  "result": {

    "id": "<RULE_ID>",

    "program_id": "<PROGRAM_ID>",

    "scope": "global",

    "name": "global",

    "mode": "monitoring",

    "expression": "",

    "created_on": "<TIMESTAMP>",

    "modified_on": "<TIMESTAMP>"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

Refer to [JSON objects](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/programmable-flow-protection/json-objects/) for more information on the fields in the JSON body.

## Create a rule with regional scope

This example creates a rule scoped to the Western Europe region with an expression filter.

Request

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/programmable_flow_protection/configs/rules" \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "program_id": "<PROGRAM_ID>",

  "scope": "region",

  "name": "WEUR",

  "mode": "enabled",

  "expression": "ip.dst in { 192.0.2.0/24 }"

}'


```

Response

```

{

  "result": {

    "id": "<RULE_ID>",

    "program_id": "<PROGRAM_ID>",

    "scope": "region",

    "name": "WEUR",

    "mode": "enabled",

    "expression": "ip.dst in { 192.0.2.0/24 }",

    "created_on": "<TIMESTAMP>",

    "modified_on": "<TIMESTAMP>"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

Refer to [JSON objects](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/programmable-flow-protection/json-objects/) for more information on the fields in the JSON body.

## Update a rule

This example updates an existing rule. You can update the mode, scope, and expression, but not the program. To change the program, delete the rule and create a new one.

Request

```

curl --request PATCH \

"https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/programmable_flow_protection/configs/rules/{rule_id}" \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "mode": "enabled"

}'


```

Response

```

{

  "result": {

    "id": "<RULE_ID>",

    "program_id": "<PROGRAM_ID>",

    "scope": "global",

    "name": "global",

    "mode": "enabled",

    "expression": "",

    "created_on": "<TIMESTAMP>",

    "modified_on": "<TIMESTAMP>"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

Refer to [JSON objects](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/programmable-flow-protection/json-objects/) for more information on the fields in the JSON body.

## Delete a rule

This example deletes an existing rule.

Request

```

curl --request DELETE \

"https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/programmable_flow_protection/configs/rules/{rule_id}" \

--header "Authorization: Bearer <API_TOKEN>"


```

Response

```

{

  "result": null,

  "success": true,

  "errors": [],

  "messages": []

}


```

## Debug a program with PCAP

This example runs a program against a PCAP file for debugging. The API returns an annotated PCAP file with the program verdict for each packet.

The request body must contain the PCAP file in binary format. The API automatically detects the IP header offset based on the input PCAP. To override automatic detection, use the optional `ip_offset` query parameter to specify the number of bytes the IP header is offset by in each packet (for example, `14` for Ethernet frames).

Request

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/programmable_flow_protection/configs/programs/{program_id}/pcap" \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/vnd.tcpdump.pcap" \

--data-binary "@/path/to/input.pcap" \

--output output.pcap


```

The output PCAP file contains the same packets as the input file, but with annotations on each packet. The Packet Comment annotation may contain:

* Program return value: `CF_EBPF_PASS` or `CF_EBPF_DROP`
* `Ignored`: if the incoming packet is not UDP
* `Analytics tag`: the custom network analytics tag set by the program on this packet, if any
* `Challenge packet`: the challenge packet emitted from the program back to the client, if any

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/","name":"API configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/programmable-flow-protection/","name":"Programmable Flow Protection"}},{"@type":"ListItem","position":6,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/programmable-flow-protection/examples/","name":"Common API calls"}}]}
```

---

---
title: JSON objects
description: JSON object structure for Programmable Flow Protection API requests and responses.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# JSON objects

This page contains examples of the JSON objects used in the Programmable Flow Protection API.

## Program

```

{

  "id": "31c70c65-9f81-4669-94ed-1e1e041e7b06",

  "name": "rate-limiter",

  "status": "success",

  "created_on": "2024-01-01T13:06:04.721954+01:00",

  "modified_on": "2024-01-01T13:06:04.721954+01:00"

}


```

| Field        | Description                                                                                                                                       |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| id           | Unique identifier for the program.                                                                                                                |
| name         | Name of the program, derived from the uploaded filename.                                                                                          |
| status       | Compilation and verification status. One of success or failed. Programs with failed status are automatically deleted after 30 days of inactivity. |
| created\_on  | Timestamp when the program was created.                                                                                                           |
| modified\_on | Timestamp when the program was last modified.                                                                                                     |

## Rule

```

{

  "id": "20b99eb6-8b48-48dd-a5b9-a995a0843b57",

  "program_id": "31c70c65-9f81-4669-94ed-1e1e041e7b06",

  "scope": "region",

  "name": "WEUR",

  "mode": "enabled",

  "expression": "ip.dst in { 192.0.2.0/24 }",

  "created_on": "2024-01-01T13:10:38.762503+01:00",

  "modified_on": "2024-01-01T13:10:38.762503+01:00"

}


```

| Field        | Description                                                                                                                                                        |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| id           | Unique identifier for the rule.                                                                                                                                    |
| program\_id  | The ID of the program this rule executes.                                                                                                                          |
| scope        | The scope of the rule. Must be one of global, region, or datacenter.                                                                                               |
| name         | For global scope, use global. For region or datacenter scope, provide the region code or datacenter code.                                                          |
| mode         | The rule mode. Must be one of enabled, disabled, or monitoring.                                                                                                    |
| expression   | A [Rules language expression](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/) to filter which packets the rule applies to. Optional. |
| created\_on  | Timestamp when the rule was created.                                                                                                                               |
| modified\_on | Timestamp when the rule was last modified.                                                                                                                         |

### Scope

The `scope` field determines where the rule executes:

* `global` — The rule executes at all Cloudflare locations. You can only create one global rule per account.
* `region` — The rule executes at all Cloudflare locations within the specified region.
* `datacenter` — The rule executes only at the specified Cloudflare datacenter.

When multiple rules match a packet, the rule with the most specific scope executes. A datacenter-scoped rule takes precedence over a region-scoped rule, which takes precedence over a global rule.

### Mode

The `mode` field determines how the rule behaves:

* `enabled` — The program runs and its verdict (pass or drop) is applied to packets.
* `disabled` — The rule is inactive and the program does not run.
* `monitoring` — The program runs but packets are never dropped, regardless of the program's verdict. Use this mode to test a program before enabling it.

### Expression

The `expression` field is a [Rules language expression](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/) up to 8,192 characters. The expression filters which packets the rule applies to. Only packets matching the expression are processed by the program.

Supported fields:

* `ip.src`
* `ip.dst`
* `udp.srcport`
* `udp.dstport`

If the expression is empty or omitted, the rule applies to all UDP packets within its scope.

For more information on rule settings, refer to [Rule settings](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#rule-settings).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/","name":"API configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/programmable-flow-protection/","name":"Programmable Flow Protection"}},{"@type":"ListItem","position":6,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/programmable-flow-protection/json-objects/","name":"JSON objects"}}]}
```

---

---
title: Advanced TCP Protection
description: Configure Advanced TCP Protection prefixes, allowlists, and rules using the API.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Advanced TCP Protection

You can configure Advanced TCP Protection using the Advanced TCP Protection API.

The Advanced TCP Protection API only supports [API token authentication](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/).

For examples of API calls, refer to [Common API calls](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/tcp-protection/examples/).

## Endpoints

To obtain the complete endpoint, append the Advanced TCP Protection API endpoints listed below to the Cloudflare API base URL.

The Cloudflare API base URL is:

```

https://api.cloudflare.com/client/v4


```

The `{account_id}` argument is the account ID (a hexadecimal string). You can find this value in the Cloudflare dashboard.

The tables in the following sections summarize the available operations.

### General operations

| Operation                             | Method and endpoint / Description                                                                                                                               |
| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Get Advanced TCP Protection status    | GET accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/tcp\_protection\_statusGets the global Advanced TCP Protection status (enabled or disabled). |
| Update Advanced TCP Protection status | PATCH accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/tcp\_protection\_statusEnables or disables Advanced TCP Protection.                        |

### Prefix operations

| Operation            | Method and endpoint / Description                                                                                                                       |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| List prefixes        | GET accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/prefixesFetches all Advanced TCP Protection prefixes in the account.                 |
| Add prefixes in bulk | POST accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/prefixes/bulkAdds prefixes in bulk to the account (up to 300 prefixes per request). |
| Get a prefix         | GET accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/prefixes/{prefix\_id}Fetches the details of an existing prefix.                      |
| Update a prefix      | PATCH accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/prefixes/{prefix\_id}Updates an existing prefix.                                   |
| Delete a prefix      | DELETE accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/prefixes/{prefix\_id}Deletes an existing prefix.                                  |
| Delete all prefixes  | DELETE accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/prefixesDeletes all existing prefixes from the account.                           |

### Allowlist operations

| Operation                       | Method and endpoint / Description                                                                                                                       |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| List allowlisted prefixes       | GET accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/allowlistFetches all prefixes in the account allowlist.                              |
| Add an allowlisted prefix       | POST accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/allowlistAdds a prefix to the allowlist.                                            |
| Get an allowlisted prefix       | GET accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/allowlist/{allowlist\_id}Fetches the details of an existing prefix in the allowlist. |
| Update an allowlisted prefix    | PATCH accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/allowlist/{allowlist\_id}Updates an existing prefix in the allowlist.              |
| Delete an allowlisted prefix    | DELETE accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/allowlist/{allowlist\_id}Deletes an existing prefix from the allowlist.           |
| Delete all allowlisted prefixes | DELETE accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/allowlistDeletes all existing prefixes from the allowlist.                        |

### SYN Flood Protection operations

#### Rules

| Operation                  | Method and endpoint / Description                                                                                                                                    |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| List SYN flood rules       | GET accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/syn\_protection/rulesFetches all SYN flood rules in the account.                                  |
| Add a SYN flood rule       | POST accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/syn\_protection/rulesAdds a SYN flood rule to the account.                                       |
| Get a SYN flood rule       | GET accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/syn\_protection/rules/{rule\_id}Fetches the details of an existing SYN flood rule in the account. |
| Update a SYN flood rule    | PATCH accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/syn\_protection/rules/{rule\_id}Updates an existing SYN flood rule in the account.              |
| Delete a SYN flood rule    | DELETE accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/syn\_protection/rules/{rule\_id}Deletes an existing SYN flood rule from the account.           |
| Delete all SYN flood rules | DELETE accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/syn\_protection/rulesDeletes all existing SYN flood rules from the account.                    |

#### Filters

| Operation                    | Method and endpoint / Description                                                                                                                                          |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| List SYN flood filters       | GET accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/syn\_protection/filtersFetches all SYN flood filters in the account.                                    |
| Add a SYN flood filter       | POST accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/syn\_protection/filtersAdds a SYN flood filter to the account.                                         |
| Get a SYN flood filter       | GET accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/syn\_protection/filters/{filter\_id}Fetches the details of an existing SYN flood filter in the account. |
| Update a SYN flood filter    | PATCH accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/syn\_protection/filters/{filter\_id}Updates an existing SYN flood filter in the account.              |
| Delete a SYN flood filter    | DELETE accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/syn\_protection/filters/{filter\_id}Deletes an existing SYN flood filter from the account.           |
| Delete all SYN flood filters | DELETE accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/syn\_protection/filtersDeletes all existing SYN flood filters from the account.                      |

### Out-of-state TCP Protection operations

#### Rules

| Operation                         | Method and endpoint / Description                                                                                                                                                 |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| List out-of-state TCP rules       | GET accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/tcp\_flow\_protection/rulesFetches all out-of-state TCP rules in the account.                                  |
| Add an out-of-state TCP rule      | POST accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/tcp\_flow\_protection/rulesAdds an out-of-state TCP rule to the account.                                      |
| Get an out-of-state TCP rule      | GET accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/tcp\_flow\_protection/rules/{rule\_id}Fetches the details of an existing out-of-state TCP rule in the account. |
| Update an out-of-state TCP rule   | PATCH accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/tcp\_flow\_protection/rules/{rule\_id}Updates an existing out-of-state TCP rule in the account.              |
| Delete an out-of-state TCP rule   | DELETE accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/tcp\_flow\_protection/rules/{rule\_id}Deletes an existing out-of-state TCP rule from the account.           |
| Delete all out-of-state TCP rules | DELETE accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/tcp\_flow\_protection/rulesDeletes all existing out-of-state TCP rules from the account.                    |

#### Filters

| Operation                           | Method and endpoint / Description                                                                                                                                                       |
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| List out-of-state TCP filters       | GET accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/tcp\_flow\_protection/filtersFetches all out-of-state TCP filters in the account.                                    |
| Add an out-of-state TCP filter      | POST accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/tcp\_flow\_protection/filtersAdds an out-of-state TCP filter to the account.                                        |
| Get an out-of-state TCP filter      | GET accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/tcp\_flow\_protection/filters/{filter\_id}Fetches the details of an existing out-of-state TCP filter in the account. |
| Update an out-of-state TCP filter   | PATCH accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/tcp\_flow\_protection/filters/{filter\_id}Updates an existing out-of-state TCP filter in the account.              |
| Delete an out-of-state TCP filter   | DELETE accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/tcp\_flow\_protection/filters/{filter\_id}Deletes an existing out-of-state TCP filter from the account.           |
| Delete all out-of-state TCP filters | DELETE accounts/{account\_id}/magic/advanced\_tcp\_protection/configs/tcp\_flow\_protection/filtersDeletes all existing out-of-state TCP filters from the account.                      |

## Pagination

The API operations that return a list of items use pagination. For more information on the available pagination query parameters, refer to [Pagination](https://developers.cloudflare.com/fundamentals/api/how-to/make-api-calls/#pagination).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/","name":"API configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/tcp-protection/","name":"Advanced TCP Protection"}}]}
```

---

---
title: Common API calls
description: Example API requests for managing Advanced TCP Protection prefixes, allowlists, and rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Common API calls

The following sections contain example requests for common API calls. For a list of available API endpoints, refer to [Endpoints](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/tcp-protection/#endpoints).

## Get Advanced TCP Protection status

This example obtains the current status of Advanced TCP Protection (enabled or disabled).

Request

```

curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/advanced_tcp_protection/configs/tcp_protection_status \

--header "Authorization: Bearer <API_TOKEN>"


```

Example response

```

{

  "result": {

    "enabled": false

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

## Enable Advanced TCP Protection

This example enables Advanced TCP Protection.

Request

```

curl --request PATCH \

https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/advanced_tcp_protection/configs/tcp_protection_status \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "enabled": true

}'


```

## Get existing prefixes

This example fetches all existing prefixes in Advanced TCP Protection.

Request

```

curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/advanced_tcp_protection/configs/prefixes \

--header "Authorization: Bearer <API_TOKEN>"


```

```

{

  "result": [

    {

      "prefix": "203.0.113/24",

      "comment": "My prefix",

      "excluded": false

    }

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

## Add prefixes

This example `POST` request adds two prefixes. The second prefix excludes a subset of the first prefix from Advanced TCP Protection.

Request

```

curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/advanced_tcp_protection/configs/prefixes/bulk \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '[

  {

    "prefix": "192.0.2.0/24",

    "comment": "Game ranges",

    "excluded": false

  },

  {

    "prefix": "192.0.2.2/26",

    "comment": "Range for a specific game",

    "excluded": true

  }

]'


```

```

{

  "result": [

    {

      "id": "<PREFIX_1_ID>",

      "prefix": "192.0.2.0/24",

      "excluded": false,

      "comment": "Game ranges",

      "created_on": "<TIMESTAMP>",

      "modified_on": "<TIMESTAMP>"

    },

    {

      "id": "<PREFIX_2_ID>",

      "prefix": "192.0.2.2/26",

      "excluded": true,

      "comment": "Range for a specific game",

      "created_on": "<TIMESTAMP>",

      "modified_on": "<TIMESTAMP>"

    }

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

## Get all prefixes in allowlist

This example fetches all the prefixes in the allowlist.

Request

```

curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/advanced_tcp_protection/configs/allowlist \

--header "Authorization: Bearer <API_TOKEN>"


```

```

{

  "result": [

    {

      "id": "<ALLOWLIST_PREFIX_ID>",

      "prefix": "192.0.2.127",

      "comment": "Single IP address in allowlist",

      "enabled": true,

      "created_on": "<TIMESTAMP>",

      "modified_on": "<TIMESTAMP>"

    }

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

## Add a prefix to the allowlist

This example `POST` request adds a prefix to the allowlist of the account.

Request

```

curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/advanced_tcp_protection/configs/allowlist \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "prefix": "203.0.113.0/26",

  "comment": "Partner range",

  "enabled": true

}'


```

```

{

  "result": {

    "id": "<ALLOWLIST_PREFIX_1_ID>",

    "prefix": "203.0.113.0/26",

    "comment": "Partner range",

    "enabled": true,

    "created_on": "<TIMESTAMP>",

    "modified_on": "<TIMESTAMP>"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

## Create a SYN flood rule

This example `POST` request creates a SYN flood rule with a regional scope (Western Europe) in monitoring mode.

Request

```

curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/advanced_tcp_protection/configs/syn_protection/rules \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "scope": "region",

  "name": "WEUR",

  "mode": "monitoring",

  "rate_sensitivity": "medium",

  "burst_sensitivity": "medium"

}'


```

```

{

  "result": {

    "id": "<SYN_FLOOD_RULE_ID>",

    "scope": "region",

    "name": "WEUR",

    "mode": "monitoring",

    "rate_sensitivity": "medium",

    "burst_sensitivity": "medium",

    "created_on": "<TIMESTAMP>",

    "modified_on": "<TIMESTAMP>"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

Refer to [JSON objects](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/tcp-protection/json-objects/) for more information on the fields in the JSON body.

## Create an out-of-state TCP rule

This example `POST` request creates an out-of-state TCP rule in monitoring mode, with a regional scope, and with low rate and burst sensitivities.

Request

```

curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/advanced_tcp_protection/configs/tcp_flow_protection/rules \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "scope": "region",

  "name": "WEUR",

  "mode": "monitoring",

  "rate_sensitivity": "low",

  "burst_sensitivity": "low"

}'


```

```

{

  "result": {

    "id": "<OOS_TCP_RULE_ID>",

    "scope": "region",

    "name": "WEUR",

    "mode": "monitoring",

    "rate_sensitivity": "low",

    "burst_sensitivity": "low",

    "created_on": "<TIMESTAMP>",

    "modified_on": "<TIMESTAMP>"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

Refer to [JSON objects](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/tcp-protection/json-objects/) for more information on the fields in the JSON body.

## Create a SYN flood filter

This example `POST` request creates a SYN flood [filter](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#filter), setting SYN flood protection to monitoring mode for a specific range of destination IP addresses.

Request

```

curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/advanced_tcp_protection/configs/syn_protection/filters \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "expression": "ip.dst in { 192.0.2.0/24 }",

  "mode": "monitoring"

}'


```

```

{

  "result": {

    "id": "<SYN_FLOOD_FILTER_ID>",

    "expression": "ip.dst in { 192.0.2.0/24 }",

    "mode": "monitoring",

    "created_on": "<TIMESTAMP>",

    "modified_on": "<TIMESTAMP>"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

Refer to [JSON objects](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/tcp-protection/json-objects/) for more information on the fields in the JSON body.

## Create an out-of-state TCP filter

This example `POST` request creates an out-of-state TCP [filter](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#filter), disabling out-of-state TCP protection for a specific range of destination IP addresses and ports.

Request

```

curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/advanced_tcp_protection/configs/tcp_flow_protection/filters \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

  "expression": "ip.dst in { 203.0.113.0/24 } and tcp.dstport in { 8000..8081 }",

  "mode": "disabled"

}'


```

```

{

  "result": {

    "id": "<OOS_TCP_FILTER_ID>",

    "expression": "ip.dst in { 203.0.113.0/24 } and tcp.dstport in { 8000..8081 }",

    "mode": "disabled",

    "created_on": "<TIMESTAMP>",

    "modified_on": "<TIMESTAMP>"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

Refer to [JSON objects](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/tcp-protection/json-objects/) for more information on the fields in the JSON body.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/","name":"API configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/tcp-protection/","name":"Advanced TCP Protection"}},{"@type":"ListItem","position":6,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/tcp-protection/examples/","name":"Common API calls"}}]}
```

---

---
title: JSON objects
description: JSON object structure for Advanced TCP Protection API requests and responses.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# JSON objects

This page contains an example of the TCP protection rule JSON object used in the API.

## Prefix

```

{

  "id": "31c70c65-9f81-4669-94ed-1e1e041e7b06",

  "prefix": "192.0.2.0/24",

  "comment": "Game ranges",

  "excluded": false,

  "created_on": "2022-01-01T13:06:04.721954+01:00",

  "modified_on": "2022-01-01T13:06:04.721954+01:00"

}


```

## Prefix in allowlist

```

{

  "id": "31c70c65-9f81-4669-94ed-1e1e041e7b06",

  "prefix": "192.0.2.0/24",

  "comment": "Game ranges",

  "enabled": true,

  "created_on": "2021-10-01T13:06:04.721954+01:00",

  "modified_on": "2021-10-01T13:06:04.721954+01:00"

}


```

The `prefix` field can contain an IP address or a CIDR range.

## SYN flood rule or out-of-state TCP rule

```

{

  "id": "31c70c65-9f81-4669-94ed-1e1e041e7b06",

  "scope": "region",

  "name": "WEUR",

  "rate_sensitivity": "medium",

  "burst_sensitivity": "medium",

  "created_on": "2021-10-01T13:10:38.762503+01:00",

  "modified_on": "2021-10-01T13:10:38.762503+01:00"

}


```

The `scope` field value must be one of `global`, `region`, or `datacenter`. You must provide a region code (or data center code) in the `name` field when specifying a `region` (or `datacenter`) scope.

The `rate_sensitivity` and `burst_sensitivity` field values must be one of `low`, `medium`, or `high`.

## Filter

```

{

  "id": "20b99eb6-8b48-48dd-a5b9-a995a0843b57",

  "expression": "ip.dst in { 192.0.2.0/24 203.0.113.0/24 } and tcp.dstport in { 80 443 10000..65535 }",

  "mode": "enabled",

  "created_on": "2022-11-01T13:10:38.762503+01:00",

  "modified_on": "2022-11-01T13:10:38.762503+01:00"

}


```

The `expression` field is a [Rules language expression](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/) up to 8,192 characters that can include the following fields:

* `ip.src`
* `ip.dst`
* `tcp.srcport`
* `tcp.dstport`

Note

Expressions of SYN flood protection and out-of-state TCP protection filters do not currently support functions.

The `mode` value must be one of `enabled`, `disabled`, or `monitoring`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/","name":"API configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/tcp-protection/","name":"Advanced TCP Protection"}},{"@type":"ListItem","position":6,"item":{"@id":"/ddos-protection/advanced-ddos-systems/api/tcp-protection/json-objects/","name":"JSON objects"}}]}
```

---

---
title: Concepts
description: Key concepts for Advanced DDoS Protection, including prefixes, allowlists, and rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Concepts

## Prefixes

Advanced DDoS Protection protects the IP prefixes you select from sophisticated DDoS attacks. A prefix can be an IP address or an IP range in CIDR format. You must add prefixes to Advanced DDoS Protection so that Cloudflare can analyze incoming packets and offer protection against sophisticated TCP DDoS attacks.

Prefixes added to Advanced DDoS Protection must be one of the following:

* A prefix [onboarded to Magic Transit](https://developers.cloudflare.com/magic-transit/how-to/advertise-prefixes/).
* A subset of a prefix [onboarded to Magic Transit](https://developers.cloudflare.com/magic-transit/how-to/advertise-prefixes/).

You cannot add a prefix (or a subset of a prefix) that you have not onboarded to Magic Transit or whose status is still _Unapproved_. Contact your account team to get help with prefix approvals.

## Allowlist

The Advanced DDoS Protection allowlist is a list of prefixes that will bypass all configured Advanced DDoS Protection rules.

For example, you could add prefixes used only by partners of your company to the allowlist so that they are exempt from packet inspection and mitigation actions performed by Advanced DDoS Protection.

Important

Prefixes in the allowlist will be vulnerable to IP spoofing attacks. If an attacker can guess the source IP addresses you have allowlisted, their packets will be allowlisted.

## Rule

A rule configures Advanced DDoS Protection for a given [scope](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#scope), according to several [settings](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#rule-settings): execution mode, burst sensitivity, and rate sensitivity.

Each system component (SYN flood protection and out-of-state TCP protection) has its own list of rules, and it should have at least one rule.

### Rule settings

Each rule type has the following settings: scope, mode, burst sensitivity, and rate sensitivity.

You may need to adjust the burst or rate sensitivity of a rule in case of false positives or due to specific traffic patterns.

#### Scope

Advanced TCP Protection rules can have one of the following scopes:

* **Global**: The rule will apply to all incoming packets.
* **Region**: The rule will apply to incoming packets in a selected region.
* **Data center**: The rule will apply to incoming packets in the selected Cloudflare data center.

The rule scope allows you to adjust the system's tolerance for out-of-state packets in locations where you may have more or less traffic than usual, or due to any other networking reasons.

When multiple rules with different scopes apply to a data center, the rule with the most specific scope takes precedence. For example, if you have both a region rule (such as Western Europe) and a data center rule (such as Marseille), traffic through Marseille will be processed according to the data center rule.

Besides defining rules with one of the above scopes, you must also select the [prefixes](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#prefixes) that you wish to protect with Advanced TCP Protection.

#### Mode

The Advanced TCP Protection system constantly learns your TCP connections to mitigate DDoS attacks. Advanced TCP Protection rules can have one of the following execution modes: monitoring, mitigation (enabled), or disabled.

* **Monitoring**  
   * In this mode, Advanced TCP Protection will not impact any packets. Instead, the protection system will learn your legitimate TCP connections and show you what it would have mitigated. Check Network Analytics to visualize what actions Advanced TCP Protection would have taken on incoming packets, according to the current configuration.  
   Refer to the [Analytics documentation](https://developers.cloudflare.com/analytics/network-analytics/configure/displayed-data/#view-logged-or-monitored-traffic) for more information on how to view logged or monitored traffic.
* **​​Mitigation (Enabled)**  
   * In this mode, Advanced TCP Protection will learn your legitimate TCP connections and perform mitigation actions on incoming TCP DDoS attacks based on the rule configuration (burst and rate sensitivity) and your [allowlist](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#allowlist).
* **Disabled**  
   * In this mode, a rule will not evaluate any incoming packets.

#### Burst sensitivity

The burst sensitivity is the rule's sensitivity to short-term bursts in the packet rate:

* A low sensitivity means that bigger spikes in the packet rate may trigger a mitigation action.
* A high sensitivity means that smaller spikes in the packet rate may trigger a mitigation action.

The default burst sensitivity is _Medium_.

#### Rate sensitivity

The rate sensitivity is the rule's sensitivity to the sustained packet rate:

* A low sensitivity means that higher sustained packet rates can trigger a mitigation action.
* A high sensitivity means that lower sustained packet rates may trigger a mitigation action. A high sensitivity offers increased protection, but you may get more false positives (that is, mitigated packets that belong to legitimate traffic).

The default rate sensitivity is _Medium_.

#### Profile sensitivity

Note

Profile sensitivity is available for [Advanced DNS Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-dns-protection/) only.

The sensitivity to DNS queries that have not been recently seen.

* A higher sensitivity level means that the mitigation system will begin mitigating faster.
* A lower sensitivity provides more tolerance for potentially suspicious DNS queries.

The default profile sensitivity and recommended setting is _Low_. You should only increase sensitivity if it is needed based on observed attacks.

## Filter

A filter modifies Advanced TCP Protection's [execution mode](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#mode) — monitoring, mitigation (enabled), or disabled — for all incoming packets matching an expression.

The filter expression can reference source and destination IP addresses and ports. Each system component (SYN flood protection and out-of-state TCP protection) should have one or more [rules](#rule), but filters are optional.

Each system component has its own filters. You can configure a filter for each execution mode:

* **Mitigation Filter**: The system will drop packets matching the filter expression.
* **Monitoring Filter**: The system will log packets matching the filter expression.
* **Off Filter**: The system will ignore packets matching the filter expression.

When there is a match, a filter will alter the execution mode for all configured rules in a given system component (SYN flood protection or out-of-state TCP protection), including disabled rules.

For instructions on creating filters in the Cloudflare dashboard, refer to [Create a filter](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/how-to/create-filter/). For API examples, refer to [Common API calls](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/tcp-protection/examples/).

### Example use case

You can create a monitor filter for a new prefix that you are onboarding by using the expression to match against the prefix.

Your already onboarded prefixes can remain protected with one or more configured rules in mitigation mode.

When onboarding a new prefix, you would configure a monitoring filter for this prefix and then add it to Advanced TCP Protection.

---

## Determining the execution mode

When you have both rules and filters configured, the execution mode is determined according to the following:

1. If there is a match for one of the configured filters, use the filter's execution mode. The filter evaluation order is based on their mode, in the following order:  
   1. Mitigation filter (filter with `enabled` mode)  
   2. Monitoring filter (filter with `monitoring` mode)  
   3. Off filter (filter with `disabled` mode)
2. If no filter matched, use the execution mode determined by existing rules.
3. If no rules match, disable Advanced TCP Protection.

---

## Mitigation reasons

The Advanced TCP Protection system applies mitigation actions for different reasons based on the connection states. The **Mitigation reason** field shown in the **Advanced TCP Protection** tab of the [Network Analytics](https://developers.cloudflare.com/analytics/network-analytics/) dashboard will contain more information on why a given packet was dropped by the system.

The connection states are the following:

* **New**: A SYN or SYN-ACK packet has been sent to attempt to open a new connection.
* **Open**: The three-way TCP handshake has been completed and the TCP connection is open.
* **Closing**: A FIN or FIN-ACK packet has been seen attempting to close a connection.
* **Closed**: The closing three-way handshake has been completed, or an RST packet has closed the connection.

The mitigation reasons are the following:

| Reason               | Description                                                                                                                                      |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Unexpected**       | Packet dropped because it was not expected given the current state of the TCP connection it was associated with.                                 |
| **Challenge needed** | Packet challenged because the system determined that the packet is most likely part of a packet flood.                                           |
| **Challenge passed** | Packet dropped because it belongs to a solved challenge.                                                                                         |
| **Not found**        | Packet dropped because it is not part of an existing TCP connection and it is not establishing a new connection.                                 |
| **Out of sequence**  | Packet dropped because its properties (for example, TCP flags or sequence numbers) do not match the expected values for the existing connection. |
| **Already closed**   | Packet dropped because it belongs to a connection that is already closed.                                                                        |

Mitigation will only occur based on your Advanced TCP Protection configuration (rule sensitivities, configured allowlists and prefixes). The protection system will provide some tolerance to out-of-state packets to accommodate for the natural randomness of Internet routing.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/concepts/","name":"Concepts"}}]}
```

---

---
title: Add a prefix
description: Add an IP prefix to Advanced DDoS Protection for monitoring and mitigation.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Add a prefix

To add a [prefix](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#prefixes) to Advanced DDoS Protection:

1. In the Cloudflare dashboard, go to the **L3/4 DDoS protection** page.  
[ Go to **DDoS Managed Rules** ](https://dash.cloudflare.com/?to=/:account/network-security/ddos)
2. Go to **Advanced Protection**.
3. Under **General settings** \> **Prefixes**, select **Edit**.
4. Expand the **Add existing prefix** section and select **Add** next to the prefix you wish to add.  
Alternatively, enter a prefix and (optionally) a description in **Prefix** and **Description**, respectively, and select **Add**.

Note

The **Add existing prefix** list will not display leased prefixes, but you can add them manually in the Cloudflare dashboard or [using the API](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/). You cannot add [delegated prefixes](https://developers.cloudflare.com/byoip/concepts/prefix-delegations/) to Advanced TCP Protection.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/how-to/","name":"How to"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/how-to/add-prefix/","name":"Add a prefix"}}]}
```

---

---
title: Add an IP or prefix to the allowlist
description: Allowlist trusted IP addresses or prefixes to exclude them from Advanced DDoS Protection.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Add an IP or prefix to the allowlist

To add an IP address or prefix to the Advanced DDoS Protection [allowlist](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#allowlist):

1. In the Cloudflare dashboard, go to the **L3/4 DDoS protection** page.  
[ Go to **DDoS Managed Rules** ](https://dash.cloudflare.com/?to=/:account/network-security/ddos)
2. Go to **Advanced Protection**.
3. Under **General settings** \> **Allowlist**, select **Edit**.
4. Enter a prefix and (optionally) a description in **Prefix** and **Description**, respectively.
5. To exclude the current prefix from the allowlist instead of including it, uncheck the **Enabled** checkbox. 6\. Select **Add**.

Allowlists support approximately 200 IP addresses in a single expression for a rule.

Important

Prefixes in the allowlist will be vulnerable to IP spoofing attacks. If an attacker can guess the source IP addresses you have allowlisted, their packets will be allowlisted.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/how-to/","name":"How to"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/how-to/add-prefix-allowlist/","name":"Add an IP or prefix to the allowlist"}}]}
```

---

---
title: Create a filter
description: Create a filter to define traffic characteristics for Advanced TCP Protection rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Create a filter

A filter modifies Advanced TCP Protection's [execution mode](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#mode) — monitoring, mitigation (enabled), or disabled — for all incoming packets matching an expression.

Each protection system component (SYN flood protection or out-of-state TCP protection) should have at least one [rule](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#rule), but filters are optional.

Note

Filters only apply to Advanced TCP Protection.

## Procedure

To create a [filter](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#filter) for one of the system components:

1. In the Cloudflare dashboard, go to the **L3/4 DDoS protection** page.  
[ Go to **DDoS Managed Rules** ](https://dash.cloudflare.com/?to=/:account/network-security/ddos)
2. Go to **Advanced Protection** \> **Advanced TCP Protection**.
3. Under the system component for which you are creating the filter (**SYN Flood Protection** or **Out-of-state TCP Protection**), select **Create** next to the type of filter you want to create:  
   * **Mitigation Filter**: The protection system will drop packets matching the filter expression. - **Monitoring Filter**: The protection system will log packets matching the filter expression.  
   * **Off Filter**: The protection system will ignore packets matching the filter expression.
4. Under **When incoming packets match**, define a filter expression using the Expression Builder (specifying one or more values for **Field**, **Operator**, and **Value**), or manually enter an expression using the Expression Editor. For more information, refer to [Edit rule expressions](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/edit-expressions/).
5. Select **Save**.

Note

Filters take precedence over rules. For details on how the execution mode is determined, refer to [Determining the execution mode](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#determining-the-execution-mode).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/how-to/","name":"How to"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/how-to/create-filter/","name":"Create a filter"}}]}
```

---

---
title: Create a rule
description: Create an Advanced DDoS Protection rule for TCP, DNS, or flow-based mitigation.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Create a rule

## Create an Advanced DNS Protection rule

1. In the Cloudflare dashboard, go to the **L3/4 DDoS protection** page.  
[ Go to **DDoS Managed Rules** ](https://dash.cloudflare.com/?to=/:account/network-security/ddos)
2. Go to **Advanced Protection** \> **Advanced DNS Protection**.
3. Select **Create Advanced DNS Protection rule**.
4. In **Mode**, select a [mode](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#mode) for the rule.
5. Under **Set scope**, select a [scope](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#scope) to determine the range of packets that will be affected by the rule.
6. Under **Sensitivity**, define the [burst sensitivity](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#burst-sensitivity), [rate sensitivity](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#rate-sensitivity), and [profile sensitivity](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#profile-sensitivity) to determine when to initiate mitigation. 9\. Select **Deploy**.

---

## Create an Advanced TCP Protection rule

To create a [SYN flood rule](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/#syn-flood-protection) or an [out-of-state TCP](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/#out-of-state-tcp-protection) rule:

1. In the Cloudflare dashboard, go to the **L3/4 DDoS protection** page.  
[ Go to **DDoS Managed Rules** ](https://dash.cloudflare.com/?to=/:account/network-security/ddos)
2. Go to **Advanced Protection** \> **Advanced TCP Protection**.
3. Depending on the rule you are creating, do one of the following:  
   * Under **SYN Flood Protection**, select **Create SYN flood rule**.  
   * Under **Out-of-state TCP Protection**, select **Create out-of-state TCP rule**.
4. In **Mode**, select a [mode](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#mode) for the rule.
5. Under **Set scope**, select a [scope](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#scope) for the rule. If you choose to apply the rule to a subset of incoming packets, select a region or a data center.
6. Under **Sensitivity**, define the [burst sensitivity](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#burst-sensitivity) and [rate sensitivity](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#rate-sensitivity) of the rule (by default, _Medium_). The sensitivity levels are based on the initially configured thresholds for your specific case.
7. Select **Deploy**.

Note

Filters take precedence over rules. For details on how the execution mode is determined, refer to [Determining the execution mode](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#determining-the-execution-mode).

---

## Create a Programmable Flow Protection rule

To create a [Programmable Flow Protection rule](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/programmable-flow-protection):

1. In the Cloudflare dashboard, go to the **L3/4 DDoS protection** page.  
[ Go to **DDoS Managed Rules** ](https://dash.cloudflare.com/?to=/:account/network-security/ddos)
2. Go to **Advanced Protection** \> **Programmable Flow Protection**.
3. In **General Settings**, select a program. The chosen program must have a status of `success`, indicating it has successfully compiled and passed verification. This field is required.
4. In **General Settings**, select a [mode](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#mode) for the rule. This field is required.
5. Under **Set scope**, optionally select a [scope](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#scope) for the rule. If you choose to apply the rule to a subset of incoming packets, select a region or a data center. The default scope setting is global.
6. Under **Set scope**, optionally select a packet filter expression. If you choose to apply a rule to a subset of incoming packets, select the IP and UDP characteristics to filter on. The default setting applies a rule to all UDP packets.
7. Select **Deploy**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/how-to/","name":"How to"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/how-to/create-rule/","name":"Create a rule"}}]}
```

---

---
title: Exclude a prefix
description: Exclude a prefix or prefix subset from Advanced DDoS Protection monitoring.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Exclude a prefix

To exclude a prefix or a prefix subset from Advanced DDoS Protection:

1. In the Cloudflare dashboard, go to the **L3/4 DDoS protection** page.  
[ Go to **DDoS Managed Rules** ](https://dash.cloudflare.com/?to=/:account/network-security/ddos)
2. Go to **Advanced Protection**.
3. [Add the prefix](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/how-to/add-prefix/) you previously onboarded to Magic Transit to Advanced TCP Protection.
4. [Add the prefix](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/how-to/add-prefix/) (or subset) you wish to exclude as a new, separate prefix in Advanced TCP Protection.
5. For the prefix you added in the previous step, select **Exclude Subset** in the **Enrolled Prefixes** list.

Note

Prefixes or subsets added as _Excluded_ will not be protected by Advanced TCP Protection.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/how-to/","name":"How to"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/how-to/exclude-prefix/","name":"Exclude a prefix"}}]}
```

---

---
title: General settings
description: Enable and configure Advanced TCP Protection, DNS Protection, and Flow Protection.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# General settings

The Advanced DDoS Protection system includes [Advanced TCP Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/), [Advanced DNS Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-dns-protection/), and [Programmable Flow Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/programmable-flow-protection/). These systems are configured using the general settings, but also comprise of their own dedicated settings. Advanced DDoS Protection systems is available to [Magic Transit](https://developers.cloudflare.com/magic-transit/) customers.

Protection for simpler TCP or DNS-based DDoS attacks is included as part of the [Network-layer DDoS Attack Protection managed ruleset](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/).

General settings enable and control the use of the Advanced TCP Protection and the Advanced DNS Protection systems, and are composed of thresholds, prefixes, rules, and enablement.

## Thresholds

Thresholds are based on your network's unique traffic and are configured by Cloudflare. The sensitivity levels manipulate the thresholds. Thresholds apply to Advanced TCP Protection and Advanced DNS protection.

When you get access to Advanced DDoS Protection systems, you are [automatically provisioned](#automatic-thresholds) with default settings in monitoring mode.

Thresholds are based on your network's individual behavior, derived from your traffic profile as monitored by Cloudflare. Defining the thresholds will effectively determine what the _High_, _Medium_, and _Low_ [sensitivities](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#burst-sensitivity) will be for your specific case.

If needed, you can change the sensitivity levels that will manipulate the thresholds for Advanced TCP Protection and Advanced DNS Protection from the default settings.

Once thresholds are configured, the Advanced DDoS Protection systems have been initialized and enabled in monitoring mode.

### Automatic thresholds

Automatic thresholds for Cloudflare's Advanced DDoS Protection system optimizes the detection and mitigation of DDoS attacks by automatically calculating appropriate traffic thresholds for each system for each customer account. This system applies to Advanced TCP Protection (specifically SYN Flood Protection and Out-of-State TCP Flood Protection) and Advanced DNS Protection.

Make sure that you have properly onboarded to the Advanced DDoS Protection system to benefit from automatic thresholds.

#### Process

The automatic threshold system calculates thresholds every 10 minutes for both new and existing Magic Transit accounts, provided they meet the requirements outlined in the process below.

* The `flowtrackd` account was created within the past 7 to 10 days.
* The account has at least one configured global threshold (rate and burst). This can be a threshold that was automatically provisioned by the system or manually provisioned by Cloudflare.

These checks are performed independently for SYN Flood Protection, Out-of-State TCP Flood Protection, and Advanced DNS Protection. The criteria does not require the presence of any rules to be configured. Accounts initially provisioned by the automatic system will have default thresholds. Otherwise, thresholds may be unconfigured if they are not set by Cloudflare.

After seven days, the system calculates a rate and burst threshold for each of the protection components. However, they are not applied. Cloudflare must review the draft thresholds produced by the automatic calculation system before creating real thresholds for your traffic.

Thresholds are applied globally per account. There is no minimum packets-per-second (pps) requirement for threshold calculation, but for those under 100 pps, the system will default to a reasonable non-zero rate and burst.

Thresholds are derived using the 95th percentile (P95) of observed traffic over the preceding seven days:

* SYN Flood Protection: Based on SYN and SYN-ACK traffic.
* Out-of-State TCP Flood Protection: Based on all other TCP flag traffic.
* Advanced DNS Protection: Based on DNS over UDP traffic.

While the calculation typically occurs automatically after seven days, Cloudflare can force an earlier calculation if you want to enable the system in protective mode in advance.

The automatic threshold calculation system does not differentiate between legitimate and attack traffic. If you are onboarded or experience attacks during the seven day observation period, the calculated thresholds may be inaccurate, depending on the attack's size, duration, and frequency relative to legitimate traffic. In such cases, Cloudflare will likely need to trigger a recalculation. Future improvements will allow you to run a recalculation without the assistance of your Cloudflare account team.

#### Implementation

You should enable the automatically provisioned rules. Initially, these rules will have default values and operate in Monitor mode. After seven days, once thresholds are calculated, you can use the Network Analytics dashboard to observe what packets would have been dropped or allowed, then safely enable the rules in mitigation mode. Depending on what is observed in the Network Analytics dashboard (for example, legitimate traffic is being flagged in Monitor mode), you may want to change the sensitivity level and continue observation before enabling in mitigation mode. Rules and Filters, where supported, can also be scoped to allow for additional granularity.

#### Recalculation

Automatic thresholds are calculated only once. Cloudflare can manually trigger a recalculation. Adding, approving, removing, delegating, advertising, or withdrawing prefixes after initial onboarding does not automatically re-trigger the calculation. It is recommended to move the relevant systems to Monitor mode before making changes that impact traffic levels and requesting a recalculation from Cloudflare. Future improvements will take these events into consideration.

#### Overrides

Automatically calculated thresholds can be overridden. Cloudflare can help manually define thresholds.

#### Considerations

If you are actively under attack and diverting traffic to Cloudflare, the automatic threshold calculation is unlikely to be effective as it will incorporate attack traffic. In these scenarios, Cloudflare will still need to manually configure thresholds. If you are not under attack while diverting traffic, Cloudflare can force a threshold calculation with available data. However, less data, such as fewer days or hours of observation, will result in less accurate thresholds.

#### Limitations

Customers currently do not have visibility into the calculated thresholds or an indication of whether thresholds have been configured. Future improvements aim to indicate when thresholds have been configured and when they were last updated.

The auto-threshold calculation component currently runs only in PDX. Therefore, this feature is not compatible if you have enabled Data Localization Services (DLS) and are located outside of the US, such as EU CMB. Future improvements will address this limitation.

---

## Prefixes

The prefixes that you have [onboarded](https://developers.cloudflare.com/magic-transit/how-to/advertise-prefixes/) to and approved by Cloudflare instruct the system on which traffic to route through the system. Prefixes apply to Advanced TCP Protection, Advanced DNS Protection, and Programmable Flow Protection.

[Add the prefixes](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/how-to/add-prefix/) you would like to use with Advanced TCP and DNS Protection. You will be able to register prefixes that you previously [onboarded to Magic Transit](https://developers.cloudflare.com/magic-transit/how-to/advertise-prefixes/) or a subset of these prefixes.

You cannot add unapproved prefixes to Advanced DDoS Protection systems. Contact your account team to get help with prefix approvals.

Optionally, you can [add prefixes to the allowlist](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/how-to/add-prefix-allowlist/) if your traffic should bypass Advanced DDoS Protection rules.

The allowlist only applies to source IPs — it does not apply to your own IPs or prefixes. You can also [exclude a subset of an onboarded prefix](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/how-to/exclude-prefix/) from Advanced TCP Protection.

Refer to [Concepts](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/) for more information.

---

## Rules

[Create a rule](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/how-to/create-rule/) for Advanced TCP Protection, Advanced DNS Protection, and Programmable Flow Protection to enable mitigation.

You can create a rule for SYN Flood Protection and another rule for Out-of-state TCP Protection, both with global scope and in monitoring mode. These rules will apply to all received packets.

Optionally, you can create [filters](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#filter) for each protection system component (SYN flood protection and out-of-state TCP protection). 

A filter modifies Advanced TCP Protection's [execution mode](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#mode) — monitoring, mitigation (enabled), or disabled — for all incoming packets matching an expression.

---

## Enablement

Enable the Advanced DDoS system and begin routing traffic through it.

1. In the Cloudflare dashboard, go to the **L3/4 DDoS protection** page.  
[ Go to **DDoS Managed Rules** ](https://dash.cloudflare.com/?to=/:account/network-security/ddos)
2. Go to **Advanced Protection** \> **General settings**.
3. Under **General settings**, toggle the feature status **On**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/overview/","name":"General settings"}}]}
```

---

---
title: Advanced DNS Protection
description: Protect against sophisticated DNS-based DDoS attacks with traffic profiling and adaptive mitigation.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Advanced DNS Protection

Cloudflare's Advanced DNS Protection, powered by [flowtrackd ↗](https://blog.cloudflare.com/announcing-flowtrackd/), provides stateful protection against DNS-based DDoS attacks, specifically sophisticated and fully randomized DNS attacks such as [random prefix attacks](https://developers.cloudflare.com/dns/dns-firewall/random-prefix-attacks/about/).

Note

Advanced TCP and DNS Protection systems are automatically enabled in `Monitor` mode with the default thresholds for new Magic Transit customers and their [authorized prefixes](https://developers.cloudflare.com/magic-transit/how-to/advertise-prefixes/).

Magic Transit customers can also enable the Advanced DDoS systems when the prefixes are ready, change the sensitivity level, or adjust the thresholds by contacting their account team.

## How it works

Cloudflare's Advanced DNS Protection works by first learning your traffic patterns and forming a baseline of the type of DNS queries you normally receive. Later, the system will be able to distinguish between legitimate and malicious queries, protecting your DNS infrastructure without impacting legitimate traffic.

Currently, the protection system only analyzes DNS over UDP (it does not include DNS over TCP).

The [Network Analytics dashboard](https://developers.cloudflare.com/analytics/network-analytics/) will display system-specific analytics for Advanced DNS Protection in the **DNS protection** tab, including the queried domains and record types.

---

## Setup

[Create a rule](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/how-to/create-rule/#create-an-advanced-dns-protection-rule) to enable Advanced DNS Protection.

---

## Data collection

Cloudflare collects DNS-related data such as query type (for example, `A` record) and the queried domains. For details, refer to [Data collection](https://developers.cloudflare.com/analytics/network-analytics/reference/data-collection/).

Warning

Currently, to disable this data collection you must remove your prefixes either in the Cloudflare dashboard or through the [Delete a prefix](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/api/tcp-protection/#prefix-operations) API operation. However, this procedure will remove the prefixes from both Advanced DNS Protection and [Advanced TCP Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/).

---

## Troubleshooting

### No data about Advanced DNS Protection in Network Analytics

If you cannot find any data related to Advanced DNS Protection in the **DNS Protection** tab of Network Analytics, it could be because one of these reasons:

* You did not [add your prefixes](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/how-to/add-prefix/) to Advanced L3/4 DDoS Protection.
* Accounts that existed before January 2025 were not automatically provisioned. If you onboarded before January 2025, Advanced DNS Protection may not have been enabled for your account.
* You do not have any DNS over UDP traffic.

---

## Related products

Advanced DNS Protection can protect you against volumetric DNS DDoS attacks. To perform DNS caching, proxying, and configuration, use the [Cloudflare DNS Firewall](https://developers.cloudflare.com/dns/dns-firewall/).

Currently, Advanced DNS Protection is not available for DNS Firewall.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/overview/","name":"General settings"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/overview/advanced-dns-protection/","name":"Advanced DNS Protection"}}]}
```

---

---
title: Advanced TCP Protection
description: Protect against sophisticated TCP-based DDoS attacks with traffic profiling and adaptive mitigation.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Advanced TCP Protection

Cloudflare's Advanced TCP Protection, powered by [flowtrackd ↗](https://blog.cloudflare.com/announcing-flowtrackd/), is a stateful TCP inspection engine used to detect and mitigate sophisticated out-of-state TCP attacks such as randomized and spoofed ACK floods or SYN and SYN-ACK floods.

Note

Advanced TCP and DNS Protection systems are automatically enabled in `Monitor` mode with the default thresholds for new Magic Transit customers and their [authorized prefixes](https://developers.cloudflare.com/magic-transit/how-to/advertise-prefixes/).

Magic Transit customers can also enable the Advanced DDoS systems when the prefixes are ready, change the sensitivity level, or adjust the thresholds by contacting their account team.

## How it works

Advanced TCP Protection can simultaneously protect against different kinds of attacks:

* Pinpointed attacks targeting a specific destination IP/port combination.
* Broad attacks targeting multiple IP addresses of an IP prefix at the same time.

Advanced TCP Protection can track TCP connections even when they move between Cloudflare data centers.

The feature offers two types of protection:

* [SYN Flood Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/#syn-flood-protection): Protects against attacks such as fully randomized SYN and SYN-ACK floods.
* [Out-of-state TCP Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/#out-of-state-tcp-protection): Protects against out-of-state TCP DDoS attacks such as fully randomized ACK floods and RST floods.

Each protection type is configured independently using rules and (optionally) filters. You should configure at least one rule for each type of protection before enabling Advanced TCP Protection.

### SYN Flood Protection

This system protects against attacks such as fully randomized SYN and SYN-ACK floods. You should configure at least one SYN flood rule before enabling Advanced TCP Protection.

In mitigation mode, SYN flood rules will challenge new connection initiation requests (SYN, SYN-ACK) if they exceed the configured packet-per-second thresholds. The threshold should be higher than the normal rate of legitimate SYN and SYN-ACK packets that your network receives. Packets below the threshold will not be challenged. Using the [rate sensitivity](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#rate-sensitivity) and [burst sensitivity](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#burst-sensitivity) settings you can increase or decrease the tolerance of SYN and SYN-ACK packets.

For more information on the configuration settings of SYN flood rules, refer to [Rule settings](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#rule-settings).

### Out-of-state TCP Protection

This system protects against out-of-state TCP DDoS attacks such as fully randomized ACK floods and RST floods. You should configure one out-of-state TCP rule before enabling Advanced TCP Protection.

In mitigation mode, out-of-state TCP rules will drop out-of-state packets that do not belong to existing (and tracked) TCP connections if their rates exceed the configured thresholds. The threshold should be higher than the normal rate of non SYN or SYN-ACK TCP packets that your network receives. Packets below the threshold will not be evaluated. Using the [rate sensitivity](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#rate-sensitivity) and [burst sensitivity](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#burst-sensitivity) settings you can increase or decrease the tolerance of out-of-state TCP packets.

For more information on the configuration settings of out-of-state TCP rules, refer to [Rule settings](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#rule-settings).

---

## Setup

[Create a global configuration](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/#rules) to set up SYN Flood and Out-of-state TCP rules and filters for Advanced TCP Protection.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/overview/","name":"General settings"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/","name":"Advanced TCP Protection"}}]}
```

---

---
title: Programmable Flow Protection (Beta)
description: Create custom flow-based rules to detect and mitigate volumetric DDoS attacks.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Programmable Flow Protection (Beta)

Programmable Flow Protection is a DDoS protection system that protects against DDoS attacks over custom or standardized Layer 7 UDP-based protocols, such as gaming protocols, financial services protocols, VoIP, telecom, and streaming. In terms of topology, it supports both asymmetric and symmetric configurations, but it will only inspect ingress traffic.

Programmable Flow Protection is currently in closed beta and available as an add-on for the [Magic Transit](https://developers.cloudflare.com/magic-transit/) ([BYOIP](https://developers.cloudflare.com/byoip/) or Cloudflare-leased IPs) service only. If you would like to enable the system, contact your account team or fill out this [form ↗](https://www.cloudflare.com/lp/programmableddosprotection/).

## How it works

The Programmable Flow Protection system allows you to write and run your own packet-layer stateful program in C across Cloudflare's global anycast network as extended Berkeley Packet Filter (eBPF) programs running in the user space. An [eBPF program ↗](https://docs.kernel.org/bpf/) is a packet filter system that allows a developer to write performant custom networking logic.

Programmable Flow Protection inspects and parses your UDP-based application's protocols (deep packet inspection) and determines the outcome of the packets based on your program. Using your custom program's logic, you can permit authorized users while actively blocking attacks.

The system is built on top of the `flowtrackd` platform, Cloudflare's stateful mitigation platform. The Programmable Flow Protection system relies on the DDoS Advanced Protection system's [general settings](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/) to operate. It respects the [prefixes](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/#prefixes) that you have selected to route through the Advanced Protection systems, as well as the [allowlist](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#allowlist). The Advanced DDoS Protection system should be [enabled](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/#enablement) for the Programmable Flow Protection system to operate.

While in beta, Cloudflare will assist and provide guidance to users to write their own code. Out-of-the-box code snippets (templates) for popular gaming protocols and VoIP protocols may be provided later on.

---

## Get started

After Programmable Flow Protection has been enabled to your account, go to **Networking** \> **L3/4 DDoS Protection** \> **Advanced Protection** in the Cloudflare dashboard. Within the **Programmable Flow Protection** tab:

1. Upload your eBPF program written in C.  
The program is validated by the system and stored in your account. The API compiles the program, then runs a verifier against the compiled program to enforce memory checks and verify program termination. If the program fails compilation or verification, the Cloudflare dashboard will return a detailed error message.
2. Create a [rule](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/how-to/create-rule/#create-a-programmable-flow-protection-rule)
3. To observe the program's behavior, check the Network Analytics dashboard and select the **Programmable Flow Protection** tab.

You can create additional rules with different [rule settings](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#rule-settings) [scoped](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#scope) to various regions and Cloudflare locations to change the [mode](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#mode) (Mitigation or Monitoring) to accommodate for your traffic patterns and business use cases.

The Programmable Flow Protection system supports the [Data Localization suite](https://developers.cloudflare.com/data-localization/).

Beta functionality limitations

For more information on beta services, refer to section 2.6 in the [Enterprise Terms of Service ↗](https://www.cloudflare.com/enterpriseterms/).

### Write a basic program

The steps below write a sample program that drops all User Datagram Protocol (UDP) traffic with an IPv6 header. It also drops traffic destined to port 66, as well as traffic that does not have some custom specific application header value in the UDP payload.

1. Add a define directive to specify the versioned helper functions in use.  
As Cloudflare adds more features to the Programmable Flow Protection API, we will publish new versions of its API. Versions are guaranteed to be backwards compatible.  
```  
#define CF_EBPF_HELPER_V0  
```
2. Include the Cloudflare eBPF header files.  
These files have [helper functions](#helper-functions) to parse the input packet data to the BPF program.  
```  
#include <cf_ebpf_defs.h>  
#include <cf_ebpf_helper.h>  
```
3. Define the entry function for packet processing.  
Your program must have the exact function signature below to properly pass Cloudflare's program verification.  
The return type `uint64_t` dictates whether Cloudflare will pass or drop a packet. The function name `cf_ebpf_main` is used as the entrypoint to the program. The argument `void *state` refers to the data Cloudflare provides as input to your BPF program.  
```  
uint64_t cf_ebpf_main(void *state)  
```
4. Cast the input argument into usable structs.  
Convert the input data into `cf_ebpf_generic_ctx`, which tells Cloudflare the data boundaries in the memory that we are reading.  
Then, declare variables for data parsing. `cf_ebpf_parsed_headers` will contain the IPv4, IPv6, and UDP headers. `cf_ebpf_packet_data` will hold a copy of the original IP packet that Cloudflare received (maximum 1,500 bytes), as well as the packet length and IP header length.  
```  
struct cf_ebpf_generic_ctx *ctx = state;  
struct cf_ebpf_parsed_headers headers;  
struct cf_ebpf_packet_data *p;  
```
5. Fill variables by calling the helper function.  
You must fill in the variables by calling the helper function `parse_packet_data`, which Cloudflare has provided in a header file included in step 2.  
The `parse_packet_data` function performs the memory checks required to pass the program verifier. The `parse_packet_data` function returns `0` on success. If it is successful, the input parameters are correctly populated. The `parse_packet_data` function returns `1` on failure. If `parse_packet_data` fails, The program must return `CF_EBPF_DROP` to drop the packet in order to pass the verifier.  
```  
if (parse_packet_data(ctx, &p, &headers) != 0) {  
    return CF_EBPF_DROP;  
}  
```  
Available values after successful parsing:  
```  
struct cf_ebpf_packet_data {  
     /* Total length of the packet. */  
     size_t   total_packet_length;  
     /* Size of the IP header. Supports IPv4 (including options) and IPv6. */  
     size_t   ip_header_length;  
     /* Bytes of the packet, starting with the IP header. */  
     uint8_t  packet_buffer[1500];  
};  
struct cf_ebpf_parsed_headers {  
     /* Pointer to the parsed IPv4 header, if present (otherwise null). */  
     struct iphdr   *ipv4;  
     /* Pointer to the parsed IPv6 header, if present (otherwise null). */  
     struct ipv6hdr *ipv6;  
     /* Pointer to the parsed UDP header. */  
     struct udphdr  *udp;  
     /* Raw pointer to the last valid byte of the packet context data. */  
     uint8_t        *data_end;  
};  
```  
For a full definition of helper functions and structures, refer to [Supported BPF helper functions and structures](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview#supported-bpf-helper-functions-and-structures).
6. Write your custom logic.  
Prior steps have established the code that should be the same for any program that you write, regardless of its logic.  
Now, you can write your own custom logic.  
Note  
Programmable Flow Protection will only give UDP packets to a BPF program.  
In the example snippet below, the program will drop any packet where the IPv6 header exists or where the UDP destination port is 66.  
It will then check the application header value in the UDP payload and verify its last byte is a fixed value `0xCF`.  
```  
 struct ipv6hdr *ipv6_hdr;  
 struct udphdr *udp_hdr;  
 ipv6_hdr = (struct ipv6hdr *)headers.ipv6;  
 if (ipv6_hdr != NULL) {  
   return CF_EBPF_DROP;  
 }  
 udp_hdr = (struct udphdr *)headers.udp;  
 if (ntohs(udp_hdr->dest) == 66) {  
     return CF_EBPF_DROP;  
 }  
 struct apphdr *app = (struct apphdr *)(udp_hdr + 1);  
 if ((uint8_t *)(app + 1) > headers.data_end) {  
     return CF_EBPF_DROP;  
 }  
 // The verifier has a special limit that it will not allow offsets  
 // beyond 65535. We need this check (token_len > 64000) in order  
 // to satisfy that, even though it is not possible.  
 uint16_t token_len = app->length;  
 if (token_len > 64000) {  
     return CF_EBPF_DROP;  
 }  
 if ((uint8_t *)(app->token + token_len) > headers.data_end) {  
     return CF_EBPF_DROP;  
 }  
 uint8_t *last_byte = app->token + token_len - 1;  
 if (*last_byte != 0xCF) {  
     return CF_EBPF_DROP;  
 }  
```
7. Pass any packets that did not get dropped by program logic by returning `CF_EBPF_PASS`.  
The currently supported return values are:  
   * `CF_EBPF_PASS = return value 0`  
   * `CF_EBPF_DROP = return value 1`  
The verifier, which runs when you upload a program to the API, will enforce that the program returns only known value types.  
```  
return CF_EBPF_PASS;  
```

For reference, the example below is the basic program in its entirety:

```

#define CF_EBPF_HELPER_V0


#include <cf_ebpf_defs.h>

#include <cf_ebpf_helper.h>


struct apphdr {

    uint8_t       version;

    uint16_t      length;   // Length of the variable-length token

    unsigned char token[0]; // Variable-length token

} __attribute__((packed));


uint64_t

cf_ebpf_main(void *state)

{

    struct cf_ebpf_generic_ctx *ctx = state;

    struct cf_ebpf_parsed_headers headers;

    struct cf_ebpf_packet_data *p;


    if (parse_packet_data(ctx, &p, &headers) != 0) {

        return CF_EBPF_DROP;

    }

    struct ipv6hdr *ipv6_hdr;

    struct udphdr *udp_hdr;

    ipv6_hdr = (struct ipv6hdr *)headers.ipv6;

    if (ipv6_hdr != NULL) {

        return CF_EBPF_DROP;

    }


    udp_hdr = (struct udphdr *)headers.udp;

    if (ntohs(udp_hdr->dest) == 66) {

        return CF_EBPF_DROP;

    }


    struct apphdr *app = (struct apphdr *)(udp_hdr + 1);

    if ((uint8_t *)(app + 1) > headers.data_end) {

        return CF_EBPF_DROP;

    }


    // The verifier has a special limit that it will not allow offsets

    // beyond 65535. We need this check (token_len > 64000) in order

    // to satisfy that, even though it is not possible.

    uint16_t token_len = app->length;

    if (token_len > 64000) {

        return CF_EBPF_DROP;

    }


    if ((uint8_t *)(app->token + token_len) > headers.data_end) {

        return CF_EBPF_DROP;

    }


    uint8_t *last_byte = app->token + token_len - 1;

    if (*last_byte != 0xCF) {

        return CF_EBPF_DROP;

    }

    return CF_EBPF_PASS;

}


```

### Write a complex program: challenge-based response

The example program below implements a UDP-based challenge-response mechanism using helper functions to maintain state between packets from the same source IP. This is useful for mitigating DDoS attacks by requiring clients to prove they can receive and respond to challenges before allowing their traffic through.

The challenge mechanism works as follows:

When a packet arrives from an unknown source IP, the program generates a challenge packet containing a random nonce and marks the source IP as "challenged" in the state table. The original packet is dropped.

If a packet arrives from a source IP that has already been challenged, the program checks if the packet contains the correct challenge response (the nonce XORed with a secret value). If the response is correct, the source IP is marked as "verified". If incorrect, the source IP is immediately blocklisted.

Packets from verified source IPs are passed through without further checks.

1. Include the Cloudflare eBPF header files and define the helper version.  
```  
#define CF_EBPF_HELPER_V0  
#include <cf_ebpf_defs.h>  
#include <cf_ebpf_helper.h>  
```
2. Define constants for the challenge-response protocol.  
The challenge response is computed by XORing the nonce with a secret value. The expiry time determines how long a challenged or verified status remains valid.  
```  
#define CHALLENGE_SECRET 0xDEADBEEFCAFEBABEULL  
#define CHALLENGE_EXPIRY_SECS 60  
#define VERIFIED_EXPIRY_SECS 3600  
```
3. Define a structure for challenge packets.  
The challenge packet contains the nonce that the client must respond to, and space for the client's response.  
```  
struct challenge_packet {  
    uint64_t nonce;        // Random nonce for this challenge  
    uint64_t response;     // Expected: nonce XOR CHALLENGE_SECRET  
};  
```
4. Define the entry function and parse the packet.  
```  
uint64_t cf_ebpf_main(void *state)  
{  
    struct cf_ebpf_generic_ctx *ctx = state;  
    struct cf_ebpf_parsed_headers headers;  
    struct cf_ebpf_packet_data *p;  
    if (parse_packet_data(ctx, &p, &headers) != 0) {  
        return CF_EBPF_DROP;  
    }  
    struct udphdr *udp_hdr = headers.udp;  
```
5. Check the source IP status using `get_src_ip_status`.  
The status indicates whether this source IP is new, challenged, verified, or blocklisted. The expiry timestamp indicates when the status expires.  
```  
    uint8_t status;  
    uint64_t expiry;  
    int ret = get_src_ip_status(&status, &expiry);  
    // Check if status has expired  
    int64_t now = timestamp();  
    if (ret == 0 && expiry > 0 && (uint64_t)now > expiry) {  
        // Status expired, treat as new connection  
        ret = -1;  
    }  
```
6. Handle verified source IPs.  
The Programmable Flow Protection platform will drop packets from blocklisted IPs before the program is invoked. There is no need to explicitly handle the blocklisted case.  
If the source IP has been verified (passed a previous challenge), allow the packet through.  
```  
    if (ret == 0 && status == CF_EBPF_SRC_IP_STATUS_VERIFIED) {  
        return CF_EBPF_PASS;  
    }  
```
7. Check if this is a challenge response from a challenged source IP.  
If the source IP was previously challenged, check if the current packet contains a valid challenge response. If the response is correct, mark the source IP as verified. If the response is incorrect, blocklist the source IP immediately.  
```  
    if (ret == 0 && status == CF_EBPF_SRC_IP_STATUS_CHALLENGED) {  
        // Get the stored nonce from user data  
        uint64_t stored_nonce;  
        if (get_src_ip_data(&stored_nonce) != 0) {  
            return CF_EBPF_DROP;  
        }  
        // Parse the challenge response from the packet payload  
        struct challenge_packet *resp = (struct challenge_packet *)(udp_hdr + 1);  
        if ((uint8_t *)(resp + 1) > headers.data_end) {  
            return CF_EBPF_DROP;  
        }  
        // Verify the response: should be nonce XOR secret  
        uint64_t expected_response = stored_nonce ^ CHALLENGE_SECRET;  
        if (resp->response == expected_response) {  
            // Correct response - mark as verified  
            set_src_ip_status(CF_EBPF_SRC_IP_STATUS_VERIFIED, VERIFIED_EXPIRY_SECS);  
            set_src_ip_data(0);  // Clear the nonce  
            return CF_EBPF_PASS;  
        }  
        // Wrong response - blocklist immediately  
        set_src_ip_status(CF_EBPF_SRC_IP_STATUS_BLOCKLISTED, 0);  
        return CF_EBPF_DROP;  
    }  
```
8. Issue a new challenge for new source IPs.  
Generate a random nonce, store it in the state table, create a challenge packet, and send it using `set_challenge`.  
```  
    // Generate a new challenge for this source IP  
    uint64_t nonce = rand();  
    // Store the nonce and mark as challenged  
    set_src_ip_status(CF_EBPF_SRC_IP_STATUS_CHALLENGED, CHALLENGE_EXPIRY_SECS);  
    set_src_ip_data(nonce);  
    // Build the challenge packet to send back  
    struct challenge_packet challenge;  
    challenge.nonce = nonce;  
    challenge.response = 0;  // Client will fill this in  
    // Set the challenge packet buffer  
    set_challenge((uint8_t *)&challenge, sizeof(challenge));  
    // Drop the original packet until client responds to challenge  
    return CF_EBPF_DROP;  
}  
```

For reference, the example below is the complex program in its entirety:

```

#define CF_EBPF_HELPER_V0


#include <cf_ebpf_defs.h>

#include <cf_ebpf_helper.h>


// Challenge-response protocol constants

#define CHALLENGE_SECRET 0xDEADBEEFCAFEBABEULL

#define CHALLENGE_EXPIRY_SECS 60

#define VERIFIED_EXPIRY_SECS 3600


// Challenge packet structure

struct challenge_packet {

    uint64_t nonce;

    uint64_t response;

};


uint64_t cf_ebpf_main(void *state)

{

    struct cf_ebpf_generic_ctx *ctx = state;

    struct cf_ebpf_parsed_headers headers;

    struct cf_ebpf_packet_data *p;


    if (parse_packet_data(ctx, &p, &headers) != 0) {

        return CF_EBPF_DROP;

    }


    struct udphdr *udp_hdr = headers.udp;


    // Check source IP status

    uint8_t status;

    uint64_t expiry;

    int ret = get_src_ip_status(&status, &expiry);


    // Check if status has expired

    int64_t now = timestamp();

    if (ret == 0 && expiry > 0 && (uint64_t)now > expiry) {

        ret = -1;  // Treat as new connection

    }


    // Handle verified source IPs - allow through

    if (ret == 0 && status == CF_EBPF_SRC_IP_STATUS_VERIFIED) {

        return CF_EBPF_PASS;

    }


    // Handle challenged source IPs - check for valid response

    if (ret == 0 && status == CF_EBPF_SRC_IP_STATUS_CHALLENGED) {

        uint64_t stored_nonce;

        if (get_src_ip_data(&stored_nonce) != 0) {

            return CF_EBPF_DROP;

        }


        // Parse challenge response from packet payload

        struct challenge_packet *resp = (struct challenge_packet *)(udp_hdr + 1);

        if ((uint8_t *)(resp + 1) > headers.data_end) {

            return CF_EBPF_DROP;

        }


        // Check response using XOR

        uint64_t expected_response = stored_nonce ^ CHALLENGE_SECRET;

        if (resp->response == expected_response) {

            // Correct response - mark as verified

            set_src_ip_status(CF_EBPF_SRC_IP_STATUS_VERIFIED, VERIFIED_EXPIRY_SECS);

            set_src_ip_data(0);

            return CF_EBPF_PASS;

        }


        // Wrong response - blocklist immediately

        set_src_ip_status(CF_EBPF_SRC_IP_STATUS_BLOCKLISTED, 0);

        return CF_EBPF_DROP;

    }


    // New source IP - issue initial challenge

    uint64_t nonce = rand();

    set_src_ip_status(CF_EBPF_SRC_IP_STATUS_CHALLENGED, CHALLENGE_EXPIRY_SECS);

    set_src_ip_data(nonce);


    struct challenge_packet challenge;

    challenge.nonce = nonce;

    challenge.response = 0;

    set_challenge((uint8_t *)&challenge, sizeof(challenge));


    return CF_EBPF_DROP;

}


```

This program demonstrates several key concepts:

* **State management**: Using `get_src_ip_status`, `set_src_ip_status`, `get_src_ip_data`, and `set_src_ip_data` to track the challenge state for each source IP.
* **Challenge emission**: Using `set_challenge` to send a challenge packet back to the client.
* **Cryptographic verification**: Using a shared secret to verify that the client correctly responded to the challenge.
* **Expiry handling**: Using timestamps to expire stale state entries.

### Write a complex program: rate limiting

The example program below implements a per-source-IP rate limiter using a fixed window algorithm. This is useful for mitigating volumetric DDoS attacks by limiting how many packets a single source IP can send within a time window.

The rate limiting mechanism works as follows:

When a packet arrives, the program retrieves the stored state for that source IP. The state contains a window start timestamp and a packet counter, packed into a single 64-bit value. If the current time is still within the window, the counter increments. If the counter exceeds the configured limit, the packet is dropped. When the window expires, the counter resets.

1. Include the Cloudflare eBPF header files and define the helper version.  
```  
#include <cf_ebpf_defs.h>  
#define CF_EBPF_HELPER_V0  
#include <cf_ebpf_helper.h>  
```
2. Define constants for the rate limit configuration.  
`RATE_LIMIT` sets the maximum number of packets allowed per window. `WINDOW_SECONDS` defines the duration of each time window in seconds.  
```  
#define RATE_LIMIT 100         // Maximum packets allowed per window  
#define WINDOW_SECONDS 60      // Time window in seconds  
```
3. Define macros to pack and unpack state data.  
The source IP state table stores a single `u64` value per source IP. To track both a timestamp and a counter, pack them into this value: the timestamp in the upper 32 bits and the counter in the lower 32 bits.  
```  
#define PACK_STATE(ts, count) (((uint64_t)(ts) << 32) | ((uint64_t)(count) & 0xFFFFFFFF))  
#define UNPACK_TIMESTAMP(data) ((uint32_t)((data) >> 32))  
#define UNPACK_COUNTER(data) ((uint32_t)((data) & 0xFFFFFFFF))  
```
4. Define the entry function and get the current timestamp.  
If the timestamp helper fails, allow the packet to avoid false positives.  
```  
uint64_t cf_ebpf_main(void *state)  
{  
    // Get current timestamp  
    int64_t now = timestamp();  
    if (now < 0) {  
        return CF_EBPF_PASS; // If timestamp fails, allow the packet  
    }  
    uint32_t now_secs = (uint32_t)now;  
```
5. Retrieve the existing state for this source IP.  
Use `get_src_ip_data` to look up whether this source IP has been seen before.  
```  
    // Try to get existing state for this source IP  
    uint64_t data;  
    int ret = get_src_ip_data(&data);  
    uint32_t window_start;  
    uint32_t counter;  
```
6. Handle the case where this is a new source IP.  
If no entry exists (return value is `-1`), this is the first packet from this source IP. Initialize the window to start now with a counter of 1.  
```  
    if (ret == -1) {  
        // No existing entry - first packet from this IP  
        // Initialize: window starts now, counter = 1  
        window_start = now_secs;  
        counter = 1;  
    }  
```
7. Handle existing source IPs and check the time window.  
If an entry exists, unpack the stored timestamp and counter. If the window has expired, reset both values. Otherwise, increment the counter and check if it exceeds the rate limit.  
```  
    } else if (ret != 0) {  
        // If there's other unknown error with getting src_ip_data, pass packet  
        return CF_EBPF_PASS;  
    } else {  
        // Entry exists - unpack the state  
        window_start = UNPACK_TIMESTAMP(data);  
        counter = UNPACK_COUNTER(data);  
        // Check if we're still in the same time window  
        if (now_secs - window_start >= WINDOW_SECONDS) {  
            // Window expired - reset counter and start new window  
            window_start = now_secs;  
            counter = 1;  
        } else {  
            // Still in same window - increment counter  
            counter++;  
            // Check if rate limit exceeded  
            if (counter > RATE_LIMIT) {  
                // Drop packet without updating state  
                return CF_EBPF_DROP;  
            }  
        }  
    }  
```
8. Store the updated state and allow the packet.  
Pack the window start timestamp and counter back into a single value and store it in the source IP state table.  
```  
    // Store updated state  
    uint64_t new_data = PACK_STATE(window_start, counter);  
    set_src_ip_data(new_data);  
    return CF_EBPF_PASS;  
}  
```

For reference, the example below is the rate limiting program in its entirety:

```

#include <cf_ebpf_defs.h>

#define CF_EBPF_HELPER_V0

#include <cf_ebpf_helper.h>


// Rate limit configuration

// This program implements a fixed (not sliding) window ratelimit.

#define RATE_LIMIT 100         // Maximum packets allowed per window

#define WINDOW_SECONDS 60      // Time window in seconds


// The source IP table holds a mapping from source IP -> custom u64. We will make the custom u64 value in the

// table hold a timestamp and a counter to accomplish a ratelimit.

//

// NOTE: the source IP table is effectively a LRU cache. If it is full, old values will be evicted.

// Values are also garbage collected from the table every 1hr.

//

// The macros below pack the timestamp (upper 32 bits) and counter (lower 32 bits) into 64-bit data

// into a value that we can store into the source IP table.

#define PACK_STATE(ts, count) (((uint64_t)(ts) << 32) | ((uint64_t)(count) & 0xFFFFFFFF))

#define UNPACK_TIMESTAMP(data) ((uint32_t)((data) >> 32))

#define UNPACK_COUNTER(data) ((uint32_t)((data) & 0xFFFFFFFF))


uint64_t cf_ebpf_main(void *state)

{

    // Get current timestamp

    int64_t now = timestamp();

    if (now < 0) {

        return CF_EBPF_PASS; // If timestamp fails, allow the packet

    }

    uint32_t now_secs = (uint32_t)now;


    // Try to get existing state for this source IP

    uint64_t data;

    int ret = get_src_ip_data(&data);

    uint32_t window_start;

    uint32_t counter;


    if (ret == -1) {

        // No existing entry - first packet from this IP

        // Initialize: window starts now, counter = 1

        window_start = now_secs;

        counter = 1;

    } else if (ret != 0) {

        // If there's other unknown error with getting src_ip_data, pass packet

        return CF_EBPF_PASS;

    } else {

        // Entry exists - unpack the state

        window_start = UNPACK_TIMESTAMP(data);

        counter = UNPACK_COUNTER(data);

        // Check if we're still in the same time window

        if (now_secs - window_start >= WINDOW_SECONDS) {

            // Window expired - reset counter and start new window

            window_start = now_secs;

            counter = 1;

        } else {

            // Still in same window - increment counter

            counter++;

            // Check if rate limit exceeded

            if (counter > RATE_LIMIT) {

                // Drop packet without updating state

                // Here is where the actual ratelimit occurs.

                return CF_EBPF_DROP;

            }

        }

    }

    // Store updated state

    uint64_t new_data = PACK_STATE(window_start, counter);

    set_src_ip_data(new_data);

    return CF_EBPF_PASS;

}


```

This program demonstrates several key concepts:

* **Bit packing**: Storing multiple values (timestamp and counter) in a single `u64` using bit shifting.
* **Fixed window rate limiting**: Tracking packet counts within discrete time windows and resetting when the window expires.
* **Graceful error handling**: Allowing packets through when helper functions fail to avoid false positives during edge cases.
* **State table behavior**: The source IP state table is an LRU cache. If it reaches capacity, old entries are evicted. Entries are also garbage collected after one hour of inactivity.

---

## State

Each program has access to its own local state. State is local to each server and is not shared between datacenters.

State is tied to a specific program. If you modify a rule's mode (disabled, monitoring, or enabled), the content of the state tables persists. However, if you modify a rule's program or the contents of the program itself, the state tables are cleared.

There are two state tables available to your program.

Warning

If an incoming packet's source IP is blocklisted in the source IP state table, the packet is immediately dropped and your program does not run.

### Source IP state table

The source IP state table stores state keyed by source IP address. Each entry contains:

| Field     | Type | Description                                                                              |
| --------- | ---- | ---------------------------------------------------------------------------------------- |
| Status    | Enum | The status of the source IP: None (0), Challenged (1), Verified (2), or Blocklisted (3). |
| User data | u64  | A user-defined value you can set for any purpose.                                        |

The default maximum capacity is 1,000 entries.

Use the following helper functions to interact with this table:

* `get_src_ip_status` — Retrieve the status of the current packet's source IP.
* `set_src_ip_status` — Set the status of the current packet's source IP.
* `get_src_ip_data` — Retrieve the user data for the current packet's source IP.
* `set_src_ip_data` — Store user data for the current packet's source IP.

### Flow state table

The flow state table stores state keyed by the 4-tuple: source IP, source port, destination IP, and destination port. Each entry contains a `u64` value you can set for any purpose.

The default maximum capacity is 10,000 entries.

Use the following helper functions to interact with this table:

* `get_flow_data` — Retrieve the user data for the current flow.
* `set_flow_data` — Store user data for the current flow.

### Cache behavior

Both state tables are LRU (least recently used) caches. If a table reaches its maximum capacity, the oldest entry is evicted to make room for new entries. Entries are also garbage collected if they have not been accessed in one hour.

---

## Helper functions

A helper function is a function provided by the Cloudflare runtime that a customer program calls.

Helper functions are crucial because the BPF Instruction Set Architecture (ISA) only supports certain system calls. For safety purposes, Cloudflare will only compile a BPF object file with a predetermined list of known libraries that a program developer cannot modify.

Note

Helper functions may be removed or changed. New helper functions may be introduced in the future as well.

The table below provides a list of currently supported helper functions:

| Function name                | Function signature                                                                                   | Description                                                                                                                                                                                                                 |
| ---------------------------- | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| rand                         | uint64\_t rand(void)                                                                                 | Generates a random unsigned integer.                                                                                                                                                                                        |
| timestamp                    | uint64\_t timestamp(void)                                                                            | Returns the current timestamp.                                                                                                                                                                                              |
| hash\_md5                    | int hash\_md5(uint8\_t \*src, size\_t src\_len, uint8\_t \*dst)                                      | Computes MD5 hash of the source buffer and stores result in destination buffer.                                                                                                                                             |
| hash\_sha256                 | int hash\_sha256(uint8\_t \*src, size\_t src\_len, uint8\_t \*dst)                                   | Computes SHA-256 hash of the source buffer and stores result in destination buffer.                                                                                                                                         |
| hash\_sha512                 | int hash\_sha512(uint8\_t \*src, size\_t src\_len, uint8\_t \*dst)                                   | Computes SHA-512 hash of the source buffer and stores result in destination buffer.                                                                                                                                         |
| hash\_crc32                  | int hash\_crc32(uint8\_t \*src, size\_t src\_len, uint8\_t \*dst)                                    | Computes CRC32 hash of the source buffer and stores result in destination buffer.                                                                                                                                           |
| hmac\_sha256                 | int hmac\_sha256(uint8\_t \*key, size\_t key\_len, uint8\_t \*msg, size\_t msg\_len, uint8\_t \*dst) | Computes HMAC-SHA256 of the message using the provided key and stores result in destination buffer.                                                                                                                         |
| hmac\_sha512                 | int hmac\_sha512(uint8\_t \*key, size\_t key\_len, uint8\_t \*msg, size\_t msg\_len, uint8\_t \*dst) | Computes HMAC-SHA512 of the message using the provided key and stores result in destination buffer.                                                                                                                         |
| hash\_blake2b512             | int hash\_blake2b512(uint8\_t \*src, size\_t src\_len, uint8\_t \*dest, size\_t dest\_len)           | Computes BLAKE2B-512 hash of the source and stores result in destination buffer.                                                                                                                                            |
| hmac\_blake2b512             | int hmac\_blake2b512(uint8\_t \*src, size\_t src\_len, uint8\_t \*dest, size\_t dest\_len)           | Computes BLAKE2B-512 HMAC of the message and stores result in the destination buffer.                                                                                                                                       |
| set\_challenge               | int set\_challenge(uint8\_t \*src, size\_t src\_len)                                                 | Sets challenge data for the current packet. If src\_len is 0, challenge buffer is reset.                                                                                                                                    |
| get\_src\_ip\_status         | uint64\_t get\_src\_ip\_status(void)                                                                 | Retrieves the status value associated with the source IP address from the state table.                                                                                                                                      |
| set\_src\_ip\_status         | int set\_src\_ip\_status(uint64\_t status)                                                           | Sets the status value associated with the source IP address in the state table.                                                                                                                                             |
| get\_src\_ip\_data           | int get\_src\_ip\_data(uint64\_t \*data)                                                             | Retrieves custom data associated with the source IP address from the state table.                                                                                                                                           |
| set\_src\_ip\_data           | int set\_src\_ip\_data(uint64\_t data)                                                               | Stores custom data associated with the source IP address in the state table.                                                                                                                                                |
| get\_flow\_data              | int get\_flow\_data(uint64\_t \*data)                                                                | Retrieves custom data associated with the current flow from the state table.                                                                                                                                                |
| set\_flow\_data              | int set\_flow\_data(uint64\_t data)                                                                  | Stores custom data associated with the current flow in the state table.                                                                                                                                                     |
| entropy                      | double entropy(uint8\_t \*src, size\_t src\_len)                                                     | Calculates the entropy of the source buffer.                                                                                                                                                                                |
| set\_network\_analytics\_tag | int set\_network\_analytics\_tag(Tag value)                                                          | Sets a custom tag for network analytics reporting. Defaults to 0 if not set.                                                                                                                                                |
| ntohs                        | uint16\_t ntohs(uint16\_t netshort)                                                                  | Converts a 16-bit integer from network byte order to host byte order.                                                                                                                                                       |
| htons                        | uint16\_t htons(uint16\_t hostshort)                                                                 | Converts a 16-bit integer from host byte order to network byte order.                                                                                                                                                       |
| ntohl                        | uint32\_t ntohl(uint32\_t netlong)                                                                   | Converts a 32-bit integer from network byte order to host byte order.                                                                                                                                                       |
| htonl                        | uint32\_t htonl(uint32\_t hostlong)                                                                  | Converts a 32-bit integer from host byte order to network byte order.                                                                                                                                                       |
| ntohll                       | uint64\_t ntohll(uint64\_t netlonglong)                                                              | Converts a 64-bit integer from network byte order to host byte order.                                                                                                                                                       |
| htonll                       | uint64\_t htonll(uint64\_t hostlonglong)                                                             | Converts a 64-bit integer from host byte order to network byte order.                                                                                                                                                       |
| parse\_packet\_data          | int parse\_packet\_data(cf\_ebpf\_generic\_ctx, cf\_ebpf\_packet\_data, cf\_ebpf\_parsed\_headers)   | Use input cf\_ebpf\_generic\_ctx and cf\_ebpf\_packet\_data to generate valid cf\_ebpf\_parsed\_headers.Upon success, cf\_ebpf\_parsed\_headers will contain valid IP and UDP headers.Returns 0 on success or 1 on failure. |

---

With the exception of `rand`, `timestamp`, `ntohs`, `htons`, `ntohl`, `htonl`, `ntohll`, and `htonll`, all helper functions return a `0` on success and non-zero value on failure.

## Program endpoints

### Upload a program

To upload a program, navigate to Networking > L3/4 DDoS protection > Advanced Protection in the Cloudflare dashboard. Then select the tab titled Programmable Flow Protection.

Under **Programs**, click the button "Upload new program." This will prompt you to select a file to upload with your `C` source code.

The Cloudflare API will receive the source code in the `C` file, compile it into BPF bytecode, and run the verifier against it.

If compilation or verification fails, the API will return a detailed error message.

If compilation and verification succeeds, Cloudflare will store the source code and object file to the account and return the program ID.

### Update a program

During the development process, you may find it useful to update the same program (identified by the same program ID) instead of repeatedly creating new programs as new resources.

To update the program, select the three dots next to your program. Then, select **Overwrite**. This will prompt you to choose a file to upload as your `C` source code.

Note

It is possible to update and overwrite a program that is currently in use by one or more rules. When doing so, you will be warned that the program is currently active and will be overwritten. However, if an active program is being updated with a program that either does not compile or can not be verified, the update will fail and the old program will continue to be in use.

### View all programs

To view all uploaded programs and their success statuses, view the table under the section entitled **Programs**.

A link icon next to the program name indicates that the program is currently in use in an active rule and may not be deleted.

### Delete a program

To delete a program, select the three dots next to the program that you wish to delete. Then, select **Delete**.

Note that you will not be able to delete a program that is referenced in an active Rule.

Note that programs that have a "failed" status (meaning they failed to compile or pass verification) will be automatically and permanently deleted after 30 days of inactivity.

---

## Rules

Only one rule executes per packet. If your account has multiple rules configured, the rule with the most specific [scope](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/concepts/#scope) executes. For example, a rule scoped to a specific colo takes precedence over a rule scoped to a region, which takes precedence over a global rule. This is why you cannot create more than one global rule.

### List all rules

To view rules and their associated rule IDs, go to **Networking** \> **L3/4 DDoS protection** \> **Advanced Protection** in the Cloudflare dashboard. Then, select **Programmable Flow Protection**.

### Create a rule

To create a rule, go to **Networking** \> **L3/4 DDoS protection** \> **Advanced Protection** in the Cloudflare dashboard. Then, select **Programmable Flow Protection**.

Under **Rules**, select **Create rule**. Fill out the corresponding fields of your new rule. You will be prompted to select a program, mode, and scope for the rule.

### Update a rule

To update an existing rule, navigate to the Rules section. Click the three dots next to the rule and select **Edit**.

You will be prompted to edit the mode and scope of the rule. You may not edit the program of the rule because that is an unsafe rollout pattern.

### Delete a rule

To delete an existing rule, navigate to the Rules section. Click the three dots next to the rule and select **Delete**.

---

## Debug Packet CAPture (PCAP)

This API endpoint debugs a program by intaking:

* A local path to the input PCAP file provided as requested data in binary format. The input PCAP file has a maximum size limit of 5 MB and will be rejected if it is too large.
* An IP offset value provided as a query parameter. This is the number of bytes that the IP header is offset by in each packet of the input PCAP file.  
For example, if the PCAP file captures Ethernet packets, the IP offset value would be 14\. This endpoint assumes that all packets in a PCAP have the same IP offset value and will otherwise parse packets incorrectly.
* The program ID provided in the request path.

This endpoint runs the referenced BPF program against the input PCAP and outputs a new annotated PCAP file. The output PCAP file will contain the exact same packets as the input PCAP file, and will also include the program verdict annotated in the **Packet Comment** section of each packet.

Request

```

curl 'https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/magic/programmable_flow_protection/configs/programs/$PROGRAM_ID/pcap' \

--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

--header "Content-Type: application/vnd.tcpdump.pcap" \

--data-binary "@<PATH_TO_INPUT_PCAP_FILE>" \

--output output.pcap


```

The Packet Comment annotation may contain:

* Program return value: `CF_EBPF_PASS` or `CF_EBPF_DROP`
* `Ignored`: if the incoming packet is not UDP
* `Analytics tag`: the custom network analytics tag set by the program on this packet, if any
* `Challenge packet`: the challenge packet emitted from the program back to the client, if any

---

## Safe program and rule deployment best practices

You will want to safely deploy and test programs without impacting existing production traffic. An initial deployment approach could be to set a global scoped rule to `disabled` and set a colo or region level scoped rule to `monitoring` with a filter expression only acting on some subset of IP traffic.

Each Cloudflare region or colo will apply the most granular rule. So, in the scenario described above, the colos or regions specified in the `monitoring` rule will execute the developer program in `monitoring` mode, while every other Cloudflare location will not execute the program at all. The `monitoring` rule would only execute on traffic that matches the filter expression.

Then, after verifying the correct behavior with Network Analytics, you can update and expand the `monitoring` rule's scope and filter expression. Eventually, you can delete the `disabled` and `monitoring` rules and apply a global `enabled` rule.

Using the `Expression` field to limit programs to a subset of IPs or prefixes and the `Mode` field to dictate whether a program actually drops packets ensures a program's safety and granularity upon rollout.

---

## Network Analytics

Traffic flowing through Programmable Flow Protection can be found in the [Network Analytics](https://developers.cloudflare.com/analytics/network-analytics/) dashboard.

In the Network Analytics dashboard, select the **Programmable Flow Protection** tab to filter traffic based on this feature. You can filter traffic by program ID, custom network analytics tags, actions, IPs, and ports.

---

## Supported BPF helper functions and structures

Our helper function definitions and verifier wrapper sources are available on [GitHub ↗](https://github.com/cloudflare/pfp-tools/tree/main/pfp-headers/include).

The section below contains function signatures for every helper function your program may call.

```

/*

* cf_ebpf_generic_ctx is passed into the BPF program

*/

struct cf_ebpf_generic_ctx

{

   /* Pointer to the beginning of the context data. */

   uint64_t data;

   /* Pointer to the end of the context data. */

   uint64_t data_end;

   /* Space for the program to store metadata. */

   uint64_t meta_data;

};


/*

* cf_ebpf_packet_data_v1 is passed into the BPF program

*/

struct cf_ebpf_packet_data {

    /* Total length of the packet. */

   size_t   total_packet_length;

   /* Size of the IP header. Supports IPv4 (including options) and IPv6. */

   size_t   ip_header_length;

   /* Bytes of the packet, starting with the IP header. */

   uint8_t  packet_buffer[1500];

};


/*

* cf_ebpf_parsed_headers can be populated from cf_ebpf_generic_ctx and

* cf_ebpf_packet_data in the BPF program

*/

struct cf_ebpf_parsed_headers {

   /* Pointer to the parsed IPv4 header, if present (otherwise null). */

   struct iphdr   *ipv4;

   /* Pointer to the parsed IPv6 header, if present (otherwise null). */

   struct ipv6hdr *ipv6;

   /* Pointer to the parsed UDP header. */

   struct udphdr  *udp;

   /* Raw pointer to the last valid byte of the packet context data. */

   uint8_t        *data_end;

};


/*

* IPv4 header, used as field of cf_ebpf_parsed_headers */

* source: https://github.com/torvalds/linux/blob/a7423e6ea2f8f6f453de79213c26f7a36c86d9a2/include/uapi/linux/ip.h#L87

*/

struct iphdr {

#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__

    uint8_t  version:4,

             ihl:4;

#else

    uint8_t  ihl:4,

             version:4;

#endif

    uint8_t  tos;

    uint16_t tot_len;

    uint16_t id;

    uint16_t frag_off;

    uint8_t  ttl;

    uint8_t  protocol;

    uint16_t check;

    uint32_t saddr;

    uint32_t daddr;

};


/*

* IPv6 header, used as field of cf_ebpf_parsed_headers

* source: https://github.com/torvalds/linux/blob/a7423e6ea2f8f6f453de79213c26f7a36c86d9a2/include/uapi/linux/ipv6.h#L118

*/

struct ipv6hdr {

#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__

    uint8_t  version:4,

             priority:4;

#else

    uint8_t  priority:4,

             version:4;

#endif

    uint8_t  flow_lbl[3];

    uint16_t payload_len;

    uint8_t  nexthdr;

    uint8_t  hop_limit;

    uint8_t  saddr[16];

    uint8_t  daddr[16];

};


/*

* UDP header, used as field of cf_ebpf_parsed_headers

* source: https://github.com/torvalds/linux/blob/a7423e6ea2f8f6f453de79213c26f7a36c86d9a2/include/uapi/linux/udp.h#L23

*/

struct udphdr {

    uint16_t source;

    uint16_t dest;

    uint16_t len;

    uint16_t check;

};


/* Function to construct cf_ebpf_parsed_headers from cf_ebpf_generic_ctx and

* cf_ebpf_packet_data_v1. Performs required memory checks to pass verifier.

* Returns 0 on success and 1 on failure (e.g., packet too short, invalid length).

* cf_ebpf_packet_data_v1 is filled with IP and UDP header data on success.

*/

static inline int parse_packet_data(

   struct cf_ebpf_generic_ctx *ctx,

   struct cf_ebpf_packet_data **out_p,

   struct cf_ebpf_parsed_headers *out_headers

);


/* Returns a random unsigned integer value. */

uint64_t rand(void);


/* Returns the current timestamp. */

uint64_t timestamp(void);


/* Computes MD5 hash of the source buffer and stores result in destination buffer. */

int hash_md5(uint8_t *src, size_t src_len, uint8_t *dst);


/* Computes SHA-256 hash of the source buffer and stores result in destination buffer. */

int hash_sha256(uint8_t *src, size_t src_len, uint8_t *dst);


/* Computes SHA-512 hash of the source buffer and stores result in destination buffer. */

int hash_sha512(uint8_t *src, size_t src_len, uint8_t *dst);


/* Computes CRC32 hash of the source buffer and stores result in destination buffer. */

int hash_crc32(uint8_t *src, size_t src_len, uint8_t *dst);


/* Computes HMAC-SHA256 of the message using the provided key and stores result in destination buffer. */

int hmac_sha256(uint8_t *key, size_t key_len, uint8_t *msg, size_t msg_len, uint8_t *dst);


/* Computes HMAC-SHA512 of the message using the provided key and stores result in destination buffer. */

int hmac_sha512(uint8_t *key, size_t key_len, uint8_t *msg, size_t msg_len, uint8_t *dst);


/* Computes BLAKE2B-512 hash of the source and stores result in destination buffer. */

int hash_blake2b512(uint8_t *src, size_t src_len, uint8_t *dest, size_t dest_len);


/* Computes BLAKE2B-512 HMAC of the message and stores result in the destination buffer. */

int hmac_blake2b512(uint8_t *src, size_t src_len, uint8_t *dest, size_t dest_len);


/* Sets challenge data for the current packet. If src_len is 0, challenge buffer is reset. */

int set_challenge(uint8_t *src, size_t src_len);


/* Retrieves the status value associated with the source IP address from the state table. */

uint64_t get_src_ip_status(void);


/* Sets the status value associated with the source IP address in the state table. */

int set_src_ip_status(uint64_t status);


/* Retrieves custom data associated with the source IP address from the state table. */

int get_src_ip_data(uint64_t *data);


/* Stores custom data associated with the source IP address in the state table. */

int set_src_ip_data(uint64_t data);


/* Retrieves custom data associated with the current flow from the state table. */

int get_flow_data(uint64_t *data);


/* Stores custom data associated with the current flow in the state table. */

int set_flow_data(uint64_t data);


/* Calculates the entropy of the source buffer. */

double entropy(uint8_t *src, size_t src_len);


/* Sets a custom tag for network analytics reporting. */

int set_network_analytics_tag(uint64_t tag);


/* Converts a 16-bit integer from network byte order to host byte order. */

uint16_t ntohs(uint16_t netshort);


/* Converts a 16-bit integer from host byte order to network byte order. */

uint16_t htons(uint16_t hostshort);


/* Converts a 32-bit integer from network byte order to host byte order. */

uint32_t ntohl(uint32_t netlong);


/* Converts a 32-bit integer from host byte order to network byte order. */

uint32_t htonl(uint32_t hostlong);


/* Converts a 64-bit integer from network byte order to host byte order. */

uint64_t ntohll(uint64_t netlonglong);


/* Converts a 64-bit integer from host byte order to network byte order. */

uint64_t htonll(uint64_t hostlonglong);


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/overview/","name":"General settings"}},{"@type":"ListItem","position":5,"item":{"@id":"/ddos-protection/advanced-ddos-systems/overview/programmable-flow-protection/","name":"Programmable Flow Protection (Beta)"}}]}
```

---

---
title: Troubleshooting Advanced TCP Protection
description: Troubleshoot common issues with Advanced TCP Protection, including mode transitions, false positives, allowlist behavior, and false negatives.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Troubleshooting Advanced TCP Protection

## Mode transition behavior

Advanced TCP Protection rules have three execution modes: **Disabled**, **Monitoring** (logs only, no drops), and **Mitigation (Enabled)** (active mitigation).

Always transition from Monitoring mode to Mitigation (Enabled) mode. Do not switch directly from Disabled to Mitigation (Enabled).

When you switch directly from Disabled to Mitigation (Enabled), Advanced TCP Protection begins a learning period to observe existing connection state. Long-lived connections that pre-date this learning period may be dropped because they have no state in the tracker.

**Recommended procedure:**

1. Set to **Monitoring** mode for at least 4 hours (longer if your network has long-lived connections).
2. Review the Monitoring mode logs in [Network Analytics](https://developers.cloudflare.com/analytics/network-analytics/) to confirm legitimate traffic patterns.
3. Switch to **Mitigation (Enabled)** mode.

## Legitimate traffic is being dropped (false positives)

Check the **Mitigation reason** field in the **Advanced TCP Protection** tab of [Network Analytics](https://developers.cloudflare.com/analytics/network-analytics/) and use the reason to identify the cause:

| Mitigation reason                | Likely cause                                                                              | Action                                                                                                  |
| -------------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| **Not found**                    | Learning period was incomplete, or long-lived connections pre-date ATP activation         | Set to Monitoring mode for 4+ hours, then switch to Mitigation (Enabled)                                |
| **Unexpected**                   | ECMP rehashing — packets from the same flow arriving at different Cloudflare data centers | Set to Monitoring mode; increase burst sensitivity threshold for affected colos; escalate if persistent |
| **Out of sequence**              | Packet reordering or packet loss in the network path                                      | Increase burst sensitivity threshold for the affected colo                                              |
| Drops during traffic spikes only | Burst sensitivity threshold too low                                                       | Increase burst sensitivity (keep rate sensitivity the same)                                             |

**Threshold tuning:** Adjust burst sensitivity before rate sensitivity. Burst sensitivity handles momentary spikes; rate sensitivity controls sustained packet rates.

## Traffic from known sources is being challenged

The ATP allowlist allows you to bypass mitigation for specific source IP prefixes. However:

* The allowlist supports approximately **200 IP addresses per allowlist expression**. For more information, refer to [Add an IP or prefix to the allowlist](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/how-to/add-prefix-allowlist/).
* The allowlist is **not a security control** — it is bypass-by-IP-address, which is vulnerable to IP address spoofing. Do not add large IP ranges (for example, entire data center IP blocks) to the allowlist.
* For large-scale legitimate traffic sources, prefer adjusting rule sensitivities rather than adding broad allowlist entries.

## Known limitations

* **TCP only:** Advanced TCP Protection covers TCP traffic. UDP and ICMP flood attacks are handled by [HTTP DDoS Attack Protection managed rulesets](https://developers.cloudflare.com/ddos-protection/managed-rulesets/) or [Cloudflare Network Firewall](https://developers.cloudflare.com/cloudflare-network-firewall/) rules.
* **ECMP "shifty flows":** When packets from the same TCP flow arrive at different Cloudflare data centers (due to ECMP load balancing upstream), ATP loses connection state and may drop packets with the **Unexpected** mitigation reason. This is a known architecture constraint. Mitigation: reduce burst sensitivity or adjust per-colo thresholds for affected colos.

## Attacks not being blocked (false negatives)

1. Confirm the rule mode is **Mitigation (Enabled)**, not **Monitoring** — Monitoring mode logs but does not drop.
2. Check that rule sensitivities are set appropriately for the attack traffic volume. Lower sensitivity means more traffic must exceed the threshold before mitigation triggers.
3. For distributed attacks spread across many source IPs and colos: adjust per-colo thresholds for the top-traffic colos.
4. Confirm filters are not bypassing the mitigation — a filter that matches attack traffic will override the rule's execution mode.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/advanced-ddos-systems/","name":"Advanced DDoS systems"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/advanced-ddos-systems/troubleshooting/","name":"Troubleshooting Advanced TCP Protection"}}]}
```

---

---
title: Concepts
description: Prevent and mitigate DDoS attacks on applications.
image: https://developers.cloudflare.com/cf-twitter-card.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/learning-paths/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Concepts

Learn the concepts behind DDoS attacks and protection, whether you are using Cloudflare or another provider.

## Objectives

By the end of this module, you will be able to:

* Explain what a DDoS attack is and how it could affect your application.
* List the common ways to prevent DDoS attacks.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/learning-paths/","name":"Learning Paths"}},{"@type":"ListItem","position":3,"item":{"@id":"/learning-paths/prevent-ddos-attacks/concepts/","name":"Concepts"}}]}
```

---

---
title: Proactive DDoS defense
description: Strengthen your application against DDoS attacks before they happen.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Proactive DDoS defense

Cloudflare's network automatically mitigates large [DDoS attacks](https://www.cloudflare.com/learning/ddos/what-is-a-ddos-attack/), but these attacks can still affect your application.

## All customers

All customers should perform the following steps to better secure their application:

1. Make sure all [DDoS managed rulesets](https://developers.cloudflare.com/ddos-protection/managed-rulesets/) are set to default settings (_High_ sensitivity level and mitigation actions) for optimal DDoS activation.
2. Deploy [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/) and [rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/) to enforce a combined positive and negative security model. Reduce the traffic allowed to your website based on your known usage.
3. Make sure your origin is not exposed to the public Internet, meaning that access is only possible from [Cloudflare IP addresses](https://developers.cloudflare.com/fundamentals/concepts/cloudflare-ip-addresses/). As an extra security precaution, we recommend contacting your hosting provider and requesting new origin server IPs if they have been targeted directly in the past.
4. If you have [Managed IP Lists](https://developers.cloudflare.com/waf/tools/lists/managed-lists/#managed-ip-lists) or [Bot Management](https://developers.cloudflare.com/bots/plans/bm-subscription/), consider using these in WAF custom rules.
5. Enable [caching](https://developers.cloudflare.com/cache/) as much as possible to reduce the strain on your origin servers, and when using [Workers](https://developers.cloudflare.com/workers/), avoid overwhelming your origin server with more subrequests than necessary.  
To help counter attack randomization, Cloudflare recommends to update your cache settings to exclude the query string as a cache key. When the query string is excluded as a cache key, Cloudflare's cache will take in unmitigated attack requests instead of forwarding them to the origin. The cache can be a useful mechanism as part of a multilayered security posture.

## Enterprise customers

In addition to the steps for all customers, Cloudflare Enterprise customers subscribed to the Advanced DDoS Protection service should consider enabling [Adaptive DDoS Protection](https://developers.cloudflare.com/ddos-protection/managed-rulesets/adaptive-protection/), which mitigates attacks more intelligently based on your unique traffic patterns.

## Magic Transit customers

In addition to the steps for all customers, Cloudflare Magic Transit customers should ensure that the [Advanced TCP Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/), [Advanced DNS Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-dns-protection/), and [Programmable Flow Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/programmable-flow-protection/) are enabled and that their configurations are optimized.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/best-practices/","name":"Best practices"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/best-practices/proactive-defense/","name":"Proactive DDoS defense"}}]}
```

---

---
title: Third-party services and DDoS protection
description: DDoS rule interactions with third-party services like Google and payment providers.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Third-party services and DDoS protection

## Using a third-party CDN in front of Cloudflare

Some Cloudflare customers choose to use a Content Delivery Network (CDN) in front of Cloudflare to cache and serve their resources.

Cloudflare recommends that you **do not use a third-party CDN in front of Cloudflare**. Some CDN providers may introduce subtleties into HTTP requests that deviate from protocol standards and/or protocol best practices. Additionally, because traffic to Cloudflare will originate from a limited set of IP addresses of the third-party CDN, in rare occasions — such as when using the Akamai CDN in front of Cloudflare — it may appear as if the CDN is launching a DDoS attack against Cloudflare due to the amount of traffic from these limited IP addresses.

Therefore, it is recommended that you **use the [Cloudflare CDN](https://developers.cloudflare.com/cache/)**, which provides the following benefits:

* You remove an additional hop between vendor data centers, thus reducing latency for your users.
* You perform DDoS filtering in the first point of contact from the Internet, which is a recommended best practice.

L3/4 DDoS mitigation accuracy

Using a third-party WAF or CDN service in front of Cloudflare can negatively impact the accuracy of L3/4 DDoS mitigation.

When traffic is proxied through another vendor, the vendor's IP addresses are available to Cloudflare's network-layer protection systems rather than the true client IP addresses. This lack of visibility into the original source can lead to less effective automated mitigation and potential false positives.

If you require specific architectures involving third-party vendors, refer to our [Deployment architectures for Magic Transit](https://developers.cloudflare.com/reference-architecture/architectures/magic-transit/#deployment-architectures-for-magic-transit) for detailed guidance on maintaining security posture in complex environments.

If you are using a third-party CDN in front of Cloudflare and Cloudflare mitigates a DDoS attack, you will still pay your first-hop CDN provider for the attack traffic that they processed before it was mitigated by Cloudflare.

### Recommended DDoS configuration adjustments

If you are using a CDN or proxy in front of Cloudflare, it is recommended that you change the action and/or sensitivity level of the following DDoS rules named:

* `HTTP requests with unusual HTTP headers or URI path (signature #1)` with the rule ID ...3486aee1
* `HTTP requests with unusual HTTP headers or URI path (signature #56)` with the rule ID ...e269dfd6
* `HTTP requests with unusual HTTP headers or URI path (signature #57)` with the rule ID ...f35a42a0
* `Requests coming from known bad sources` with the rule ID ...3a679c52

You should change the rule's action to _Log_ (only available on Enterprise plans) to view the flagged traffic in the [analytics dashboard](https://developers.cloudflare.com/ddos-protection/reference/analytics/). Alternatively, change the rule's **Sensitivity Level** to _Essentially Off_ to prevent the rule from being triggered.

For more information, refer to [HTTP DDoS Attack Protection managed ruleset: Ruleset configuration](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/#ruleset-configuration).

## Using VPNs, NATs, and other third-party services

Some Cloudflare Magic Transit customers operate Virtual Private Networks (VPN) so that their remote employees can connect securely to the organization's services. Additionally, larger organizations have Network Addressing Translation (NAT) systems that manage connections in and out of their network.

Cloudflare Magic Transit customers may also use third-party services such as Zoom, Webex, Microsoft Teams, and others for their internal organization communication. Because traffic to Cloudflare will be originating from a limited set of IP addresses belonging to these third-party services, it may appear as if the services are launching a DDoS attack against Cloudflare due to the amount of traffic from limited IP addresses.

Additionally, since this traffic may also be targeting a limited set of destinations (for example, the same designated service ports, VPN endpoints, or NAT IP addresses), it may appear as if the CDN is launching a DDoS attack against Cloudflare due to the amount of traffic from a limited set of IPs _to_ a limited set of IPs.

### Recommended DDoS configuration adjustments

If your organization uses VPNs, NATs, or third-party services at high rates of over 100 Mbps, it is recommended that you one of the following:

* Change the **Sensitivity Level** of the relevant rules to a lower level. Changing the level to _Essentially Off_ will prevent the rules from being triggered. Refer to [HTTP DDoS Attack Protection managed ruleset](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/) and [Network-layer DDoS Attack Protection managed ruleset](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/) for more information on the available adjustments per ruleset and how to perform them.
* Exclude the desired traffic from the Managed DDoS rule using expression filters. You can exclude a combination of source ports, source IP addresses, destination ports, destination IP addresses, and protocol. For more information, refer to [Configure Network-layer DDoS Attack Protection via API](https://developers.cloudflare.com/ddos-protection/managed-rulesets/network/network-overrides/configure-api/).

If you are on an Enterprise plan, you can change a rule's action to _Log_ to view the flagged traffic in the [analytics dashboard](https://developers.cloudflare.com/ddos-protection/reference/analytics/). After gathering this information, you can later define rule adjustments as previously described.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/best-practices/","name":"Best practices"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/best-practices/third-party/","name":"Third-party services and DDoS protection"}}]}
```

---

---
title: Alerts
description: Configure DDoS attack notifications via email, webhook, or PagerDuty.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Alerts

Configure notifications to receive real-time alerts (within \~1 minute) about L3/4 and L7 DDoS attacks on your Internet properties, depending on your plan and services. You can choose from different delivery methods.

Each notification email includes the following information:

* Description
* Detection and mitigation time of attack
* Attack type
* Maximum rate of attack
* Attack target (zone, host, or IP address)
* Rule that matched the attack (ID and description)
* Rule override, if any

Cloudflare automatically sends weekly summaries of detected and mitigated DDoS attacks to Magic Transit and Spectrum BYOIP customers. Monthly application security reports are available for WAF/CDN customers. For more information, refer to [DDoS reports](https://developers.cloudflare.com/ddos-protection/reference/reports/).

Note

DDoS reports and DDoS alerts are independent: DDoS reports will include information about any attacks for which you received DDoS alerts.

## Set up a notification for DDoS alerts

To set up a notification:

1. In the Cloudflare dashboard, go to the **Notifications** page.  
[ Go to **Notifications** ](https://dash.cloudflare.com/?to=/:account/notifications)
2. Select **Add**.
3. Select one of the [available DDoS alerts](https://developers.cloudflare.com/ddos-protection/reference/alerts/#alert-types) depending on your plan and services:  
   * HTTP DDoS Attack Alert  
   * Layer 3/4 DDoS Attack Alert  
   * Advanced HTTP DDoS Attack Alert  
   * Advanced Layer 3/4 DDoS Attack Alert
4. Enter a notification name and (optionally) a description.
5. Configure a delivery method for the notification. The available delivery methods depend on your Cloudflare plan. For more information, refer to [Cloudflare Notifications](https://developers.cloudflare.com/notifications/).
6. If you are creating a notification for one of the advanced DDoS attack alerts, select **Next** and define the parameters that will filter the notifications you will receive.
7. Select **Save**.

## Edit an existing notification

To edit, delete, or disable a notification, go to your [account notifications ↗](https://dash.cloudflare.com/?to=/:account/notifications).

---

## Alert types

Cloudflare can issue notifications for different types of DDoS attack alerts.

### Standard alerts

HTTP DDoS Attack Alert

**Who is it for?**

[WAF](https://developers.cloudflare.com/waf/) or [CDN](https://developers.cloudflare.com/cache/) customers who want to receive a notification when Cloudflare has mitigated HTTP attacks that generate more than 100 requests per second.

**Other options / filters**

None.

**Included with**

All Cloudflare plans.

**What should you do if you receive one?**

No action needed. Refer to [DDoS alerts](https://developers.cloudflare.com/ddos-protection/reference/alerts/) for more information.

Layer 3/4 DDoS Attack Alert

**Who is it for?**

[BYOIP](https://developers.cloudflare.com/byoip/) and [Spectrum](https://developers.cloudflare.com/spectrum/) customers with [Network Analytics](https://developers.cloudflare.com/analytics/network-analytics/) who want to receive a notification when Cloudflare has mitigated attacks that generate an average of at least 12,000 packets per second over a five-second period, with a duration of one minute or more.

**Other options / filters**

None.

**Included with**

Purchase of Magic Transit and/or BYOIP.

**What should you do if you receive one?**

No action needed. Refer to [DDoS alerts](https://developers.cloudflare.com/ddos-protection/reference/alerts/) for more information.

### Advanced alerts

Note

The availability of advanced DDoS attack alerts depends on your Cloudflare plan and subscribed services. Refer to [Availability](#availability) for details.

Advanced DDoS attack alerts support additional configuration, allowing you to filter the notifications you wish to receive.

Advanced HTTP DDoS Attack Alert

**Who is it for?**

[WAF](https://developers.cloudflare.com/waf/) or [CDN](https://developers.cloudflare.com/cache/) customers with the [Advanced DDoS Protection](https://developers.cloudflare.com/ddos-protection/) subscription who want to receive a notification when Cloudflare has mitigated attacks that generate more than the configured number of requests per second (100 rps by default).

**Other options / filters**

You can choose when to trigger a notification.

Available filters include:

* The zones in the account for which you wish to receive notifications.
* The specific hostnames for which you wish to receive notifications.
* The minimum requests-per-second rate that will trigger the alert (100 rps by default).
**Included with**

Enterprise plans with the Advanced DDoS Protection add-on.

**What should you do if you receive one?**

No action needed. Refer to [DDoS alerts](https://developers.cloudflare.com/ddos-protection/reference/alerts/) for more information.

Advanced Layer 3/4 DDoS Attack Alert

**Who is it for?**

[BYOIP](https://developers.cloudflare.com/byoip/) and [Magic Transit](https://developers.cloudflare.com/magic-transit/) customers with [Network Analytics](https://developers.cloudflare.com/analytics/network-analytics/) who want to receive a notification when Cloudflare has mitigated attacks that generate more than the configured number of packets per second (12,000 pps by default).

**Other options / filters**

You can choose when to trigger a notification.

Available filters include:

* The IP prefixes for which you wish to receive notifications.
* The specific IP addresses for which you wish to receive notifications.
* The minimum packets-per-second rate that will trigger the alert (12,000 pps by default).
* The minimum megabits-per-second rate that will trigger the alert.
* The protocols for which you wish to receive notifications (all protocols by default).

If you specify multiple filters, Cloudflare applies an `AND` logic. This means the alert will only trigger if all filters you set are true. Keep this in mind when setting up this alert with more than one filter.

**Included with**

Purchase of Magic Transit and/or BYOIP (Enterprise plans).

**What should you do if you receive one?**

No action needed. Refer to [DDoS alerts](https://developers.cloudflare.com/ddos-protection/reference/alerts/) for more information.

You will also receive alerts for rules with a _Log_ action, containing information on what triggered the alert.

## Availability

The available alerts depend on your Cloudflare plan and subscribed services:

| Alert type                           | WAF/CDN | Spectrum | Spectrum BYOIP | Magic Transit |
| ------------------------------------ | ------- | -------- | -------------- | ------------- |
| HTTP DDoS Attack Alert               | Yes     | –        | –              | –             |
| Advanced HTTP DDoS Attack Alert      | Yes1    | –        | –              | –             |
| Layer 3/4 DDoS Attack Alert          | –       | Yes2, 3  | Yes            | Yes3          |
| Advanced Layer 3/4 DDoS Attack Alert | –       | –        | Yes2           | Yes2          |

1 _Only available to Enterprise customers with the Advanced DDoS Protection subscription._   
2 _Only available on an Enterprise plan._   
3 _Refer to [Final remarks](#final-remarks) for additional notes._

## Example notification

The following image shows an example notification delivered via email:

![Example notification email of a DDoS attack](https://developers.cloudflare.com/_astro/ddos-notification-example.c2rVlJvC_Z1qrIXz.webp) 

To investigate a possibly ongoing attack, select **View Dashboard**. To go to the rule details in the Cloudflare dashboard, select **View Rule**.

## Final remarks

* Spectrum and Magic Transit customers using [assigned Cloudflare IP addresses](https://developers.cloudflare.com/magic-transit/cloudflare-ips/) will receive layer 3/4 DDoS attack alerts where the attacked target is the Cloudflare IP or prefix. If you have [brought your own IP (BYOIP)](https://developers.cloudflare.com/byoip/) to Cloudflare Spectrum or Magic Transit, you will see your own IP addresses or prefixes as the attacked target.
* In some cases, HTTP DDoS attack alerts will reference the attacked zone name instead of the attacked hostname. This occurs when the attack signature does not include information on the attacked hostname because it is not a strong indicator for identifying attack requests. For more information on attack signatures, refer to [How DDoS protection works](https://developers.cloudflare.com/ddos-protection/about/how-ddos-protection-works/).
* DDoS alerts are currently only available for DDoS attacks detected and mitigated by the [DDoS managed rulesets](https://developers.cloudflare.com/ddos-protection/managed-rulesets/). Alerts are not yet available for DDoS attacks detected and mitigated by the [Advanced TCP Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/), the [Advanced DNS Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-dns-protection/), or the [Programmable Flow Protection](https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/programmable-flow-protection/) system.
* You will not receive duplicate DDoS alerts within the same one-hour time frame.
* If you configure more than one alert type for the same kind of attack (for example, both an HTTP DDoS Attack Alert and an Advanced HTTP DDoS Attack Alert) you may get more than one notification when an attack occurs. To avoid receiving duplicate notifications, delete one of the configured alerts.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/reference/alerts/","name":"Alerts"}}]}
```

---

---
title: Analytics
description: View DDoS attack analytics in Security Analytics, Network Analytics, or the GraphQL API.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Analytics

You can view DDoS analytics in different dashboards, depending on your service and plan:

* The [Security Events dashboard](https://developers.cloudflare.com/waf/analytics/security-events/) provides you with visibility into L7 security events that target your zone, including HTTP DDoS attacks and TCP attacks. The dashboard displays mitigations of HTTP DDoS attacks as HTTP DDoS events. These events are also available via [Cloudflare Logs](https://developers.cloudflare.com/logs/).
* The [Network Analytics dashboard](https://developers.cloudflare.com/analytics/network-analytics/) provides you with visibility into L3/4 traffic and DDoS attacks that target your IP ranges or Spectrum applications.

## Availability

| Service        | Free              | Pro             | Business        | Enterprise        |
| -------------- | ----------------- | --------------- | --------------- | ----------------- |
| WAF/CDN        | Sampled logs only | Security Events | Security Events | Security Events   |
| Spectrum/BYOIP | –                 | –               | –               | Network Analytics |
| Magic Transit  | –                 | –               | –               | Network Analytics |

## Remarks

In some situations, the analytics dashboards will not show you the ID of the DDoS managed rule that handled a packet/request. This means that an internal DDoS rule, which Cloudflare does not currently expose publicly, applied an action to the packet/request. These internal DDoS rules have a very low false positive rate and should always be enabled to protect your properties against DDoS attacks. For the same reason, DDoS rule IDs may also be unavailable in Cloudflare logs and API responses.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/reference/analytics/","name":"Analytics"}}]}
```

---

---
title: Logs
description: Access DDoS attack event details through Logpush and activity logs.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Logs

Retrieve HTTP events using [Cloudflare Logs](https://developers.cloudflare.com/logs/) to integrate them into your SIEM systems.

Additionally, if you are a Magic Transit or a Spectrum customer on an Enterprise plan, you can export L3/4 traffic and DDoS attack logs using the [Network Analytics logs](https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/account/network%5Fanalytics%5Flogs/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/reference/logs/","name":"Logs"}}]}
```

---

---
title: Reports
description: View and share DDoS attack reports from the Cloudflare dashboard.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Reports

To download an ad-hoc DDoS report, generate a PDF report file by selecting **Print report** in your [analytics dashboard](https://developers.cloudflare.com/ddos-protection/reference/analytics/).

WAF/CDN customers can download a monthly report in Account Home > **Security Center**, by selecting [Security Reports](https://developers.cloudflare.com/analytics/account-and-zone-analytics/app-security-reports/) and downloading the desired monthly report.

Additionally, if you are a Magic Transit or Spectrum BYOIP customer, you will receive weekly DDoS reports by email with a snapshot of the DDoS attacks that Cloudflare detected and mitigated in the previous week.

Note

To receive DDoS reports by email you must have opted in to the **Analytics** category in the [communication preferences](https://developers.cloudflare.com/fundamentals/user-profiles/customize-account/#notifications) for your profile.

## Weekly DDoS reports

Cloudflare sends DDoS reports via email from `no-reply@notify.cloudflare.com` to users with the Super Administrator role on accounts with prefixes advertised by Cloudflare.

Reports contain the following information:

* Total number of DDoS attacks
* Largest DDoS attack in packets per second (pps) and bits per second (bps)
* Changes in DDoS attacks compared to the previous report
* Top attack protocols
* Top targeted IP addresses
* Top targeted destination ports
* Total potential downtime prevented (a sum of the duration of all attacks in that week)
* Total bytes mitigated (a sum of all the mitigated attack traffic)

Cloudflare issues DDoS reports via email each Tuesday. Reports summarize the attacks that occurred from Monday of the previous week to Sunday of the current week. For example, a report issued on 2020-11-10 (Tuesday) summarizes activity from 2020-11-02 (Monday) to 2020-11-08 (Sunday).

To receive real-time attack alerts, configure [DDoS alerts](https://developers.cloudflare.com/ddos-protection/reference/alerts/).

Notes

* Information about top attack protocols, IP addresses, and destination ports is temporarily unavailable in weekly DDoS reports. Use the [Network Analytics dashboard](https://developers.cloudflare.com/analytics/network-analytics/) to get this information.
* DDoS reports and DDoS alerts are independent: DDoS reports will include information about any attacks for which you received DDoS alerts.

### Example report

The following image shows an example DDoS report:

![Example email sent with a weekly DDoS report](https://developers.cloudflare.com/_astro/ddos-report-email.meVYnmIT_Z5AHUW.webp) 

When Cloudflare does not detect any L3/4 DDoS attacks in the prior week, Cloudflare sends a confirmation report:

![Example report email sent when Cloudflare does not detect any DDoS attack in the previous week](https://developers.cloudflare.com/_astro/ddos-report-no-attacks.DOx1yQA2_ZBJVFd.webp) 

### Manage reporting subscriptions

Magic Transit and Spectrum BYOIP customers will receive the weekly DDoS report automatically.

To stop receiving DDoS reports, select the unsubscribe link at the bottom of the report email. To resubscribe after opting out, contact Cloudflare support.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/reference/reports/","name":"Reports"}}]}
```

---

---
title: Simulating test DDoS attacks
description: Guidelines for simulating DDoS attacks to test protection, reporting, and alerting.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ddos-protection/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Simulating test DDoS attacks

After onboarding to Cloudflare, you may want to simulate DDoS attacks against your Internet properties to test the protection, [reporting](https://developers.cloudflare.com/ddos-protection/reference/reports/), and [alerting](https://developers.cloudflare.com/ddos-protection/reference/alerts/) mechanisms. Follow the guidelines in this section to simulate a DDoS attack.

You can only launch DDoS attacks against your own Internet properties — your zone, Spectrum application, or IP range (depending on your Cloudflare services) — and provided that:

* The Internet properties are not shared with other organizations or individuals.
* The Internet properties have been onboarded to Cloudflare in an account under your name or ownership.

## Before you start

You do not have to obtain permission from Cloudflare to launch a DDoS attack simulation against your own Internet properties.

It is recommended that you choose the right service and enable the correct features to test against the corresponding DDoS attacks. For example, if you want to test Cloudflare against an HTTP DDoS attack and you are only using Magic Transit, the test is going to fail because you need to onboard your HTTP application to Cloudflare's reverse proxy service to test our HTTP DDoS Protection.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ddos-protection/","name":"DDoS Protection"}},{"@type":"ListItem","position":3,"item":{"@id":"/ddos-protection/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ddos-protection/reference/simulate-ddos-attack/","name":"Simulating test DDoS attacks"}}]}
```

---

---
title: Cloudflare DMARC Management
description: Stop brand impersonation.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/dmarc-management/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Cloudflare DMARC Management

Stop brand impersonation.

 Available on all plans 

When someone receives an email that claims to be from your domain, email servers check whether that message is authentic. Three DNS-based mechanisms handle this verification:

* **[SPF (Sender Policy Framework) ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/)** confirms the email was sent from an IP address or domain your domain authorizes.
* **[DKIM (DomainKeys Identified Mail) ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/)** authenticates the sender's domain and verifies the email content was not altered in transit, using a cryptographic signature.
* **[DMARC (Domain-based Message Authentication Reporting and Conformance) ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-dmarc-record/)** ties SPF and DKIM together and tells receiving servers what to do when a check fails (for example, reject the email, quarantine it, or take no action).

Cloudflare DMARC Management helps you track every source that is sending emails from your domain and review DMARC reports for each source. These reports show whether messages sent from your domain are passing SPF, DKIM, and DMARC checks — so you can identify unauthorized senders and protect your domain from being used in phishing or spoofing attacks.

Note

DMARC Management is available to all Cloudflare customers with [Cloudflare DNS](https://developers.cloudflare.com/dns/).

---

## Related products

**[Email security](https://developers.cloudflare.com/cloudflare-one/email-security/)** 

Protect your email inbox with Email security.

**[Cloudflare DNS](https://developers.cloudflare.com/dns/)** 

Fast, resilient and easy-to-manage DNS service.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dmarc-management/","name":"DMARC Management"}}]}
```

---

---
title: Enable DMARC Management
description: Allow Cloudflare to process DMARC reports for your apex domain.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/dmarc-management/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Enable DMARC Management

You need to enable DMARC Management to allow Cloudflare to process DMARC reports on your behalf. DMARC Management only works with apex domains (for example, `example.com`, not `blog.example.com`) and not domains in [subdomain setups](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/).

A warning on DMARC Management and SPF records

DMARC Management does not support modifications to SPF records when a CNAME record in your zone points to an external domain. Any changes to the SPF record could invalidate your DMARC policy, as Cloudflare cannot update the associated external DNS records. We recommend managing SPF updates directly through the external domain's DNS provider.

To enable DMARC Management:

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Email** \> **DMARC Management**.
3. Select **Enable DMARC Management**.
4. DMARC Management will scan your zone for DMARC records, and will present you with two outcomes:  
   * If no DMARC record is found, Cloudflare will automatically invite you to add one that you can edit later. Select **Add** to continue.  
   * If a DMARC record is found in your zone, Cloudflare will add another `rua` (Reporting URI for Aggregate data) entry to it. The `rua` tag specifies the URI (typically a `mailto:` address) where aggregate DMARC reports are sent. This additional entry uses a Cloudflare email address so that Cloudflare can receive and process DMARC reports on your behalf. Select **Next** to continue.

DMARC Management (beta) is now active. However, it may take up to 24 hours to receive your first DMARC report and to display this information in DMARC Management.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dmarc-management/","name":"DMARC Management"}},{"@type":"ListItem","position":3,"item":{"@id":"/dmarc-management/enable/","name":"Enable DMARC Management"}}]}
```

---

---
title: Security records
description: Learn how to configure SPF records, DKIM records, and DMARC records in your Cloudflare account to help improve email security.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/dmarc-management/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Security records

Without email authentication records, anyone can send email that appears to come from your domain — a technique known as domain spoofing. To prevent this, you add DNS TXT records (text-based entries in your domain's DNS settings) that allow receiving mail servers to verify whether an email actually came from you:

* [Sender Policy Framework (SPF) ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/): Lists the IP addresses and domains authorized to send email on behalf of your domain.
* [DomainKeys Identified Mail (DKIM) ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/): Authenticates the sender's domain and verifies that email content was not altered in transit, using a cryptographic signature.
* [Domain-based Message Authentication Reporting and Conformance (DMARC) ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-dmarc-record/): Tells receiving servers what to do when SPF or DKIM checks fail (for example, reject or quarantine the email), and sends you aggregate reports about your email traffic.

Note

For additional background on email security records, refer to the [introductory blog post ↗](https://blog.cloudflare.com/tackling-email-spoofing/).

## Create security records

To set up email security records:

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Email** \> **DMARC Management**.
3. In **Email record overview**, select **View records**.
4. Use the available options to set up [SPF ↗](https://www.cloudflare.com/en-gb/learning/dns/dns-records/dns-spf-record/), [DKIM ↗](https://www.cloudflare.com/en-gb/learning/dns/dns-records/dns-dkim-record/), and [DMARC records ↗](https://www.cloudflare.com/en-gb/learning/dns/dns-records/dns-dmarc-record/). This page will also list any previous records you might already have in your account.

## Edit or delete records

Refer to [Manage DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/) for more information.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dmarc-management/","name":"DMARC Management"}},{"@type":"ListItem","position":3,"item":{"@id":"/dmarc-management/security-records/","name":"Security records"}}]}
```

---

---
title: DNS lookup limit
description: Review number of DNS lookups on your SPF records
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/dmarc-management/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# DNS lookup limit

An [SPF record ↗](https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/) lists which servers are authorized to send email for your domain. SPF records can reference other domains and services (for example, using `include:` or `mx` mechanisms), and each such reference requires a separate DNS lookup to verify. The [SPF specification (RFC 7208) ↗](https://www.rfc-editor.org/rfc/rfc7208.html) limits the total number of these lookups to 10 per SPF check. If your SPF record exceeds this limit, receiving mail servers may treat the SPF check as a permanent error and reject or flag your emails.

To check if your SPF records are compliant with the SPF specification:

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Email** \> **DMARC Management**.
3. In **Email record overview**, select **View records**.
4. Find your SPF record, and select the three dots next to it > **Edit**.
5. DMARC Management will inspect your records and check for the total number of DNS lookups. If the record exceeds the limit, DMARC Management will display a warning. To fix this, remove unnecessary entries in your SPF record. Refer to [Manage DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#delete-dns-records) for more information.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dmarc-management/","name":"DMARC Management"}},{"@type":"ListItem","position":3,"item":{"@id":"/dmarc-management/dns-lookup-limits/","name":"DNS lookup limit"}}]}
```

---

---
title: Statistics and details
description: Review whether emails sent on your behalf passed DMARC, SPF, and DKIM checks.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/dmarc-management/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Statistics and details

DMARC Management (beta) allows you to review whether emails sent on your behalf passed or failed DMARC, SPF, and DKIM authentication checks.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Email** \> **DMARC Management**.
3. The graph shows the volume of emails over a selected time period. Use the dropdown to select a period of up to 30 days.
4. Moving your mouse through the graph gives you details for a particular day. Select **View reports** for a list of DMARC reports by date.
5. Select one of the dates shown to open a window with more details.

## Source details

The Top 10 sources section shows you details about the top sources sending emails on your behalf, with information such as total volume of emails and how these sources fared regarding security policies.

You also have access to information about all third parties, and can drill down for further details on each of them:

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and domain.
2. Go to **Email** \> **DMARC Management**.
3. Select **View all**.
4. The next page shows you a list of all sources sending email on your behalf. You can filter this list by time period.
5. Find a source you want to inspect further, and select the three dots in front of it > **Details** to learn more about that third party.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/dmarc-management/","name":"DMARC Management"}},{"@type":"ListItem","position":3,"item":{"@id":"/dmarc-management/statistics/","name":"Statistics and details"}}]}
```

---

---
title: Cloudflare Firewall Rules
description: Create rules to inspect and act on incoming HTTP traffic.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Cloudflare Firewall Rules

Cloudflare Firewall Rules allows you to create rules that inspect incoming traffic and block, challenge, log, or allow specific requests.

Deprecation notice

Cloudflare Firewall Rules has been deprecated. Cloudflare has moved existing firewall rules to [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/). For more information on this change, refer to the [upgrade guide](https://developers.cloudflare.com/waf/reference/legacy/firewall-rules-upgrade/).

## Main features

* **Rule-based protection**: Use pre-defined rulesets provided by Cloudflare, or define your own firewall rules. Create rules in the Cloudflare dashboard or via API.
* **Complex custom rules**: Each rule's expression can reference multiple fields from all the available HTTP request parameters and fields, allowing you to create complex rules.

## Availability

This table outlines the Firewall Rules features and entitlements available with each customer plan:

| Free              | Pro            | Business       | Enterprise     |       |
| ----------------- | -------------- | -------------- | -------------- | ----- |
| Availability      | Yes            | Yes            | Yes            | Yes   |
| Number of rules   | 5              | 20             | 100            | 1,000 |
| Supported actions | All except Log | All except Log | All except Log | All   |
| Regex support     | No             | No             | Yes            | Yes   |

## Next steps

* Unless you are already an advanced user, refer to [Expressions](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/) and [Actions](https://developers.cloudflare.com/firewall/cf-firewall-rules/actions/) to learn more about the basic elements of firewall rules.
* To start building your own firewall rules, refer to one of the following pages:  
   * [Manage firewall rules in the dashboard](https://developers.cloudflare.com/firewall/cf-dashboard/create-edit-delete-rules/)  
   * [Manage firewall rules via the APIs](https://developers.cloudflare.com/firewall/api/)
* You can also manage firewall rules through Terraform. For more information, refer to [Getting Started with Terraform ↗](https://blog.cloudflare.com/getting-started-with-terraform-and-cloudflare-part-1/).

## Related resources

* [Cloudflare Rules language](https://developers.cloudflare.com/ruleset-engine/rules-language/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}}]}
```

---

---
title: About
description: Learn how Cloudflare Firewall Rules work.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# About

Cloudflare Firewall Rules is a flexible and intuitive framework for filtering HTTP requests. It gives you fine-grained control over which requests reach your applications, proactively inspecting incoming site traffic and automatically responding to threats.

Deprecation notice

Cloudflare Firewall Rules has been deprecated. Cloudflare has moved existing firewall rules to [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/). For more information on this change, refer to the [upgrade guide](https://developers.cloudflare.com/waf/reference/legacy/firewall-rules-upgrade/).

In a firewall rule you define an [expression](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/) that tells Cloudflare what to look for in a request, and specify the appropriate [action](https://developers.cloudflare.com/firewall/cf-firewall-rules/actions/) to take when those conditions are met. Expressions can reference [IP lists](https://developers.cloudflare.com/waf/tools/lists/custom-lists/#ip-lists) \- groups of IP addresses that you can reference collectively by name.

To write firewall rule expressions, use the [Rules language](https://developers.cloudflare.com/ruleset-engine/rules-language/), a powerful expression language inspired in the Wireshark Display Filter language.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/cf-firewall-rules/","name":"About"}}]}
```

---

---
title: Firewall rules actions
description: Review available actions for firewall rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Firewall rules actions

The action of a firewall rule tells Cloudflare how to handle HTTP requests that have matched the rule expression.

Deprecation notice

Cloudflare Firewall Rules has been deprecated. Cloudflare has moved existing firewall rules to [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/). For more information on this change, refer to the [upgrade guide](https://developers.cloudflare.com/waf/reference/legacy/firewall-rules-upgrade/).

## Supported actions

The table below lists the actions available in firewall rules. These actions are listed in order of precedence. If the same request matches two different rules which have the same priority, precedence determines the action to take.

For example, the _Allow_ action takes precedence over the _Block_ action. In a case where a request matches a rule with the _Allow_ action and another with the _Block_ action, precedence resolves the tie, and Cloudflare allows the request.

There are two exceptions to this behavior: the _Log_ and _Bypass_ actions. Unlike other actions, _Log_ and _Bypass_ do not terminate further evaluation within firewall rules. This means that if a request matches two different rules and one of those rules specifies the _Log_ or _Bypass_ action, the second action will be triggered instead, even though _Log_/_Bypass_ has precedence.

Note

For reference information on rule actions available for Cloudflare products powered by the Ruleset Engine, refer to [Rules language: Actions](https://developers.cloudflare.com/ruleset-engine/rules-language/actions/).

| Action                                                | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | Order of precedence |
| ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
| **Log**API value: log                                 | Records matching requests in the Cloudflare Logs.Only available for Enterprise plans.Recommended for validating rules before committing to a more severe action.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | 1                   |
| **Bypass**API value: bypass                           | Allows user to dynamically disable Cloudflare security features for a request.Available to all plans.Matching requests exempt from evaluation by a user-defined list containing one or more of the following Cloudflare security features:[User Agent Blocking](https://developers.cloudflare.com/waf/tools/user-agent-blocking/)[Browser Integrity Check](https://developers.cloudflare.com/waf/tools/browser-integrity-check/)[Hotlink Protection](https://developers.cloudflare.com/waf/tools/scrape-shield/hotlink-protection/)[Security Level (IP Reputation)](https://developers.cloudflare.com/waf/tools/security-level/)[Rate Limiting](https://developers.cloudflare.com/waf/reference/legacy/old-rate-limiting/) (previous version, deprecated)[Zone Lockdown](https://developers.cloudflare.com/waf/tools/zone-lockdown/)[WAF managed rules](https://developers.cloudflare.com/waf/reference/legacy/old-waf-managed-rules/) (previous version, deprecated)**Notes:**Currently, you cannot bypass Bot Fight Mode. For more information on this product, refer to [Cloudflare bot solutions](https://developers.cloudflare.com/bots/).You cannot bypass the new [WAF managed rules](https://developers.cloudflare.com/waf/managed-rules/) using this action, only the previous version of WAF managed rules. To skip one or more managed rules in the new WAF for specific requests,[ create an exception](https://developers.cloudflare.com/waf/managed-rules/waf-exceptions/).Requests which match the _Bypass_ action are still subject to evaluation (and thus a challenge or block) within Firewall Rules, based on the order of execution. | 2                   |
| **Allow**API value: allow                             | Matching requests are exempt from _Bypass_, _Block_, and challenge actions triggered by other firewall rules.The scope of the _Allow_ action is limited to firewall rules; matching requests are **not** exempt from action by other Cloudflare security products such as Bot Fight Mode, IP Access Rules, and WAF Managed Rules.Matched requests will be mitigated if they are part of a DDoS attack.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | 3                   |
| **Interactive Challenge**API value: challenge         | This option is not recommended. Instead, choose **Managed Challenge**, which issues interactive challenges to visitors only when necessary.The client that made the request must pass an interactive challenge.If successful, Cloudflare accepts the matched request; otherwise, it is blocked.For additional information, refer to [Notes about challenge actions](#notes-about-challenge-actions).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | 4                   |
| **Managed Challenge**API value: managed\_challenge    | Helps reduce the lifetimes of human time spent solving interactive challenges across the Internet.Depending on the characteristics of a request, Cloudflare will dynamically choose the appropriate type of challenge from the following actions based on specific criteria:Show a non-interactive challenge page.Show an interactive challenge (such as requiring the visitor to click a button or to perform a task).For additional information, refer to [Notes about challenge actions](#notes-about-challenge-actions).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | 5                   |
| **Non-Interactive Challenge**API value: js\_challenge | Useful for ensuring that bots and spam cannot access the requested resource; browsers, however, are free to satisfy the challenge automatically.The client that made the request must pass a Non-Interactive Cloudflare challenge before proceeding.If successful, Cloudflare accepts the matched request; otherwise, it is blocked.For additional information, refer to [Notes about challenge actions](#notes-about-challenge-actions).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | 6                   |
| **Block**API value: block                             | Matching requests are denied access to the site.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | 7                   |

## Notes about challenge actions

When you configure a firewall rule with one of the challenge actions — _Non-Interactive Challenge_, _Managed Challenge_, or _Interactive Challenge_ — and a request matches the rule, one of two things can happen:

* The request is blocked if the visitor fails the challenge
* The request is allowed if the visitor passes the challenge

In this last case, no further firewall rules will be processed. This means that the action of any later rules with a challenge or _Block_ action also matching the request will not be applied, and the request will be allowed.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/cf-firewall-rules/","name":"About"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/cf-firewall-rules/actions/","name":"Firewall rules actions"}}]}
```

---

---
title: Order and priority
description: Understand firewall rule evaluation order and priority.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Order and priority

Cloudflare Firewall Rules, now deprecated, is part of a larger evaluation chain for HTTP requests, as illustrated in the diagram below. For example, Firewall Rules only evaluates requests that first clear IP Access rules. If a request is blocked by a rule at any stage in the chain, Cloudflare does not evaluate the request further.

![Flow chart of request evaluation at Cloudflare for security products that are not powered by the Ruleset Engine](https://developers.cloudflare.com/_astro/firewall-rules-order-and-priority-1.DvL3658y_ZAScv3.webp) 

Warning

* You can use [IP Access rules](https://developers.cloudflare.com/waf/tools/ip-access-rules/) to allowlist requests under certain conditions, effectively excluding these requests from all security checks. However, allowing a given country code will not bypass [WAF Managed Rules](https://developers.cloudflare.com/waf/managed-rules/) or [WAF managed rules (previous version)](https://developers.cloudflare.com/waf/reference/legacy/old-waf-managed-rules/).
* The execution order diagram does not include products powered by the [Ruleset Engine](https://developers.cloudflare.com/ruleset-engine/) like the [WAF](https://developers.cloudflare.com/waf/) or [Transform Rules](https://developers.cloudflare.com/rules/transform/).

By default, Cloudflare evaluates firewall rules in **list order**, where rules are evaluated in the order they appear in the firewall rules list. List ordering is convenient when working with small numbers of rules because you can manage their order by dragging and dropping them into position. However, as the number of rules grows, managing rules in list order becomes difficult. This is where priority order comes into play.

When **priority ordering** is enabled, Cloudflare evaluates firewall rules in order of their **priority number**, starting with the lowest. If a request matches two rules with the same priority, action precedence is used to resolve the tie. In this case, only the action of the rule with the highest precedence is executed, unless that action is _Log_ or _Bypass_ (refer to [Firewall rules actions](https://developers.cloudflare.com/firewall/cf-firewall-rules/actions/#supported-actions) for details). Priority ordering makes it a lot easier to manage large numbers of firewall rules, and once the number of rules passes 200, Cloudflare requires it.

## Managing rule evaluation by list order

Users with relatively small numbers of firewall rules (no more than 200) will find that list ordering is enabled by default. When list ordering is enabled, the rules list allows you to drag and drop firewall rules into position, as shown below:

![Animation of a firewall rule being moved into a new position in the rules list to reorder it](https://developers.cloudflare.com/_astro/firewall-rules-order-and-priority-2.od1TBIqG_191dc1.webp) 

Once there are more than 200 total rules, including inactive rules, you must manage evaluation using priority ordering. When you cross this threshold, the firewall rules interface automatically switches to priority ordering.

## Managing rule evaluation by priority order

Although priority ordering is enabled automatically when the number of active and inactive firewall rules exceeds 200, you can manually enable priority ordering at any time from the rules list.

Cloudflare Firewall Rules does not impose default priorities, and you are not required to set a priority for every rule.

### Enable priority ordering

To manually enable priority ordering:

1. Above the rules list, select **Ordering**.
2. Select _Priority Numbers_.

Once priority ordering is enabled, you can set a priority number for each firewall rule.

### Set rule priority

To set the priority number for a firewall rule:

1. Locate the desired rule in the rules list and select **Edit** (wrench icon).
2. In the **Edit firewall rule** panel, enter a positive integer value in **Priority**.  
![Editing a firewall rule in the dashboard to define its Priority value](https://developers.cloudflare.com/_astro/firewall-rules-order-and-priority-4.BOS_CRyn_ZJ6D6f.webp)
3. Select **Save**.

The **Priority** column in the rules list displays the priority value for each rule.

![When using priority order, the Firewall rules tab displays the priority of each rule \(if any\) in the first column of the rules list](https://developers.cloudflare.com/_astro/firewall-rules-order-and-priority-5.DaI_uWtJ_ZAqXM9.webp) 

## Working with priority ordering

Cloudflare has designed priority ordering to be extremely flexible. This flexibility is particularly useful for managing large rulesets programmatically via the Cloudflare API. Use the Update firewall rules command to set the `priority` property. Refer to [Cloudflare API: Firewall rules](https://developers.cloudflare.com/api/resources/firewall/subresources/rules/methods/list/) for details.

While your priority numbering scheme can be arbitrary, keep the following in mind:

* **The evaluation sequence starts from the lowest priority number** and goes to the highest.
* **Rules without a priority number are evaluated last**, in order of their action precedence. For example, a rule with the _Log_ action is evaluated before a rule that has the _Block_ action. For more on action precedence, refer to [Firewall rules actions](https://developers.cloudflare.com/firewall/cf-firewall-rules/actions/).
* **Avoid using the number `1` as a priority** to make rule order modification easier in the future.
* **Consider grouping ranges of priority numbers into categories** that have some meaning for your deployment. Here are some examples:  
   * 5000-9999: Trusted IP addresses  
   * 10000-19999: Blocking rules for bad crawlers  
   * 20000-29999: Blocking rules for abusive users/spam

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/cf-firewall-rules/","name":"About"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/cf-firewall-rules/order-priority/","name":"Order and priority"}}]}
```

---

---
title: Manage rules in the dashboard
description: Create and manage firewall rules in the dashboard.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Manage rules in the dashboard

To configure firewall rules in the Cloudflare dashboard, open **Firewall rules** in **Security** \> **WAF**.

Deprecation notice

Cloudflare Firewall Rules has been deprecated. Cloudflare has moved existing firewall rules to [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/). For more information on this change, refer to the [upgrade guide](https://developers.cloudflare.com/waf/reference/legacy/firewall-rules-upgrade/).

As depicted in the image below, the **Firewall rules** dashboard interface lets you:

* View the list of existing rules, both enabled and disabled.
* [Create, edit, and delete](https://developers.cloudflare.com/firewall/cf-dashboard/create-edit-delete-rules/) firewall rules.
* Enable or disable rules.
* Search and filter the list of existing rules.
* Reorder firewall rules when using [list ordering](https://developers.cloudflare.com/firewall/cf-firewall-rules/order-priority/#managing-rule-evaluation-by-list-order).
![The Firewall rules interface, displaying a list of three example firewall rules. This interface allows you to create new firewall rules, manage existing rules, and search and filter the list of rules.](https://developers.cloudflare.com/_astro/cf-firewall-rules-panel.CO2_wOo8_Z13BiF2.webp) 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/cf-dashboard/","name":"Manage rules in the dashboard"}}]}
```

---

---
title: Create, edit, and delete rules
description: Create, edit, and delete firewall rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Create, edit, and delete rules

A firewall rule has two main attributes: an [expression](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/) and an [action](https://developers.cloudflare.com/firewall/cf-firewall-rules/actions/).

Deprecation notice

Cloudflare Firewall Rules has been deprecated. Cloudflare has moved existing firewall rules to [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/). For more information on this change, refer to the [upgrade guide](https://developers.cloudflare.com/waf/reference/legacy/firewall-rules-upgrade/).

When an incoming HTTP request matches a firewall rule expression, Cloudflare performs the specified action. For more information, refer to [Expressions](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/) and [Actions](https://developers.cloudflare.com/firewall/cf-firewall-rules/actions/).

Note

The maximum length of a rule expression is 4,096 characters.

## Create a firewall rule

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), and select your account and website.
2. Go to **Security** \> **WAF** \> **Firewall rules**.
3. Select **Create a firewall rule**.
4. In the **Create firewall rule** page that displays, use the **Rule name** input to supply a descriptive name.
5. Under **When incoming requests match**, use the **Field** drop-down list to choose an HTTP property (refer to the [Fields reference](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/) for details). For each request, the value of the property you choose for **Field** is compared to the value you specify for **Value**.  
Alternatively, use the [Expression Editor](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/edit-expressions/#expression-editor) to define the rule expression.  
![Example firewall rule expression with a selected field, operator, and value](https://developers.cloudflare.com/_astro/firewall-rules-expression-builder-value.Cm4ecLGt_Z2889J7.webp)
6. Use the **Operator** drop-down list to choose a comparison operator. For an expression to match, the value of the request **Field** and the value specified in the **Value** input must satisfy the comparison operator.
7. Next, specify the value to match. If the value is an enumeration, then the **Value** control will be a drop-down list. Otherwise, it will be a text input.
8. To add a new sub-expression to the rule expression, select **And** or **Or** next to **Value**.
9. Select an action for your rule in the **Action** drop-down list.
10. To save and deploy your rule, select **Deploy**. If you are not ready to deploy your rule, select **Save as draft**.

After you choose an option, you return to the rules list, which displays your new rule.

## Manage rules

Use the available options in the rules list to manage firewall rules.

![The rules list interface in the dashboard where you can manage firewall rules](https://developers.cloudflare.com/_astro/cf-firewall-rules-list.Co9nTUAW_1s39la.webp) 

### Edit rule

Select **Edit** (wrench icon) located on the right of your rule in the rules list to open the **Edit firewall rule** panel and make the changes you want.

### Enable or disable rule

Use the toggle switch associated with a firewall rule to enable or disable it.

### Delete rule

1. Next to the rule you want to delete, select **Delete** (**X** icon).
2. In the confirmation dialog, select **Delete** to complete the operation.

### Order rules

By default, Cloudflare evaluates firewall rules in **list order**, where rules are evaluated in the order they appear in the rules list. When list ordering is enabled, the rules list allows you to drag and drop firewall rules into position, as shown below.

![Animation of a user dragging and dropping a rule in the rules list to reorder it](https://developers.cloudflare.com/images/firewall/firewall-rules-expression-builder-10.gif) 

Once there are more than 200 total rules (including inactive rules), you must manage evaluation using **priority ordering**, in which Cloudflare evaluates firewall rules in order of their **priority number**, starting with the lowest. When you cross this threshold, the firewall rules interface automatically switches to priority ordering. For more on working with priority ordering, refer to [Order and priority](https://developers.cloudflare.com/firewall/cf-firewall-rules/order-priority/).

## Test firewall rules with Rule Preview

Rule Preview allows customers on an Enterprise plan to understand the potential impact of a new firewall rule, by testing it against a sample of requests drawn from the last 72 hours of traffic.

Rule Preview is built into the **Create firewall rule** and **Edit firewall rule** panels so that you can test a rule as you edit it. For more information, refer to [Preview rules](https://developers.cloudflare.com/firewall/cf-dashboard/rule-preview/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/cf-dashboard/","name":"Manage rules in the dashboard"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/cf-dashboard/create-edit-delete-rules/","name":"Create, edit, and delete rules"}}]}
```

---

---
title: Create a mTLS rule
description: Create a mutual TLS rule in the dashboard.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Create a mTLS rule

Use the [Mutual TLS](https://developers.cloudflare.com/api-shield/security/mtls/configure/) Rule interface in the Cloudflare dashboard to create an mTLS rule that requires requests to your API or web application to present a valid client certificate.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/cf-dashboard/","name":"Manage rules in the dashboard"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/cf-dashboard/create-mtls-rule/","name":"Create a mTLS rule"}}]}
```

---

---
title: Preview rules
description: Test firewall rule impact before deployment.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Preview rules

The expression of a firewall rule can become quite complex. In this situation, you should test your firewall rule before deploying it to ensure that the rule will behave as expected.

Rule Preview helps you understand the potential impact of a firewall rule, by testing the rule against a sample drawn from the last 72 hours of traffic. Rule Preview is built into the firewall rules Expression Editor so that you can test a rule as you edit it.

Warning

Rule Preview is only available to customers on an Enterprise plan.

## Test a firewall rule with Rule Preview

1. Locate the desired rule in the rules list and select **Edit** (wrench icon).
2. Select **Test rule** to trigger the test.
![The Test Rule button next to the Action drop-down list allows you to check the traffic that would be affected by the current firewall rule](https://developers.cloudflare.com/_astro/firewall-rules-preview-1.D1bW7NGh_1NSm7x.webp) 

The results of the test are displayed in a plot that simulates how many of the total requests in the last 72 hours would have matched the tested expression.

In this screenshot, a rule that matches all User-Agents that contain the string `Mozilla` would block about 8% of requests to the zone:

![Example chart of a rule preview operation, stating that about 8% of the zone requests would be blocked by the current rule](https://developers.cloudflare.com/_astro/cf-firewall-rules-preview-rule-plot-chart.BW_d_L46_ZUJAvP.webp) 

## Important notes

**Consider the results of Firewall Preview an _indication_ of traffic levels**, not an exact calculation. The sample rate can be as little as 1% of your total traffic.

**Rule Preview does not take into account other firewall rules** that you have already configured. In effect, Rule Preview tests a single firewall rule in isolation. Security events or any other rules with a higher priority that may have blocked or challenged a request are ignored.

**You cannot test firewall rules that reference [IP lists](https://developers.cloudflare.com/waf/tools/lists/custom-lists/#ip-lists)**.

**Cloudflare does not store the entirety of requests, so only a limited number of fields are available to Rule Preview**. The table below lists the fields that Rule Preview supports (green cells), broken down by operator. Fields and operators that are not supported are not included in this table.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/cf-dashboard/","name":"Manage rules in the dashboard"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/cf-dashboard/rule-preview/","name":"Preview rules"}}]}
```

---

---
title: Manage rules via the APIs
description: Manage firewall rules programmatically via APIs.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Manage rules via the APIs

Cloudflare offers APIs that work together to achieve the same effect as the UI-based **Firewall rules** feature under **Security** \> **WAF**.

Deprecation notice

Cloudflare Firewall Rules has been deprecated. Cloudflare has moved existing firewall rules to [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/). For more information on this change, refer to the [upgrade guide](https://developers.cloudflare.com/waf/reference/legacy/firewall-rules-upgrade/).

These APIs are the following:

* [**Firewall Rules API**](https://developers.cloudflare.com/firewall/api/cf-firewall-rules/): Manage firewall rules and their actions, based on criteria separately defined through filters.
* [**Filters API**](https://developers.cloudflare.com/firewall/api/cf-filters/): Manage the filters that enable rule matching.
* [**Lists API**](https://developers.cloudflare.com/waf/tools/lists/lists-api/): Manage named lists of items (such as IP addresses) that you can use in the rules of different Cloudflare products.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}}]}
```

---

---
title: Call sequence
description: Recommended API call sequence for firewall rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Call sequence

The API call examples in this site illustrate the **recommended sequence** of calling the two APIs (the [Cloudflare Filters API](https://developers.cloudflare.com/firewall/api/cf-filters/) and the [Firewall Rules API](https://developers.cloudflare.com/firewall/api/cf-firewall-rules/)).

Deprecation notice

Cloudflare Firewall Rules has been deprecated. Cloudflare has moved existing firewall rules to [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/). For more information on this change, refer to the [upgrade guide](https://developers.cloudflare.com/waf/reference/legacy/firewall-rules-upgrade/).

The image below depicts this sequence, which can be applied for creating and editing rules. The reverse would apply for delete operations.

![Recommended flow for calling the Cloudflare Filters API and Firewall Rules API when creating or editing rules](https://developers.cloudflare.com/_astro/recommended-flow.DBuGef-x_Z1MtD3V.webp) 

Cloudflare recommends this sequence because it facilitates filter reusability and allows working with either API independently. Thanks to the standalone nature of Cloudflare Filters, the same filter can be shared in multiple firewall rules and in other future Cloudflare products and features.

For example, a filter that matches all traffic for your API (that is, `http.request.uri.path matches "^/api/.*$"`) may disable caching, disable human CAPTCHAs, configure JSON custom errors, and appear in a firewall rule. With the recommended sequence above, you would repeat steps 3-6 for every Cloudflare feature to configure against the same filter created in steps 1-2.

However, for a `POST` operation, the **simplified sequence** — shown below — allows you to create both a filter and rule in the same call. In this case, the filter and rule only refer to each other.

![Basic flow for invoking the Firewall Rules API to create both a filter and a rule in a single call](https://developers.cloudflare.com/_astro/simple-flow.DifdHPUG_Z1uWBix.webp) 

In this sequence, a single `POST` request to the `/firewall/rules` endpoint takes the filter object in the JSON to create the filter in the Filters API (also via a `POST` request). If successful, the firewall rule is created.

Below is an example call and response using this method:

Request

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/firewall/rules" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data '[

  {

    "filter": {

      "expression": "http.request.uri.path contains \"/api/\" and ip.src eq 93.184.216.34"

    },

    "action": "block"

  }

]'


```

Response

```

{

  "result": [

    {

      "id": "<RULE_ID>",

      "paused": false,

      "action": "block",

      "priority": null,

      "filter": {

        "id": "<FILTER_ID>",

        "expression": "http.request.uri.path contains \"/api/\" and ip.src eq 93.184.216.34",

        "paused": false

      }

    }

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

However, this approach has some disadvantages:

* The firewall rules client has to implement error and exception handling for every potential failure occurring in both the firewall rules and the filters APIs.
* To protect against accidentally modifying or deleting filters used by other Cloudflare features, the `PUT` or `DELETE` operations are not allowed.

By default, if either the filter or rule is invalid, neither will be created.

However, one exception applies. If you are about to exceed your rule quota, Cloudflare may create the filter but not the firewall rule. This happens because the rule is only created after the filter in the sequence diagram.

After you resolve the issue of exceeding your quota or requesting a feature that is unavailable to your zone, return to the recommended flow to create a rule that references the filter.

In summary, Cloudflare strongly recommends the sequence with the two API calls. Limit your rule and filter creation using the simplified sequence for emergency situations, and only via `curl` requests.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/call-sequence/","name":"Call sequence"}}]}
```

---

---
title: Cloudflare Filters API
description: Manage filters for firewall rules via the API.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Cloudflare Filters API

**Cloudflare Filters** is an API-only component of firewall rules for designing complex criteria that rely on boolean operators and other logic to examine incoming HTTP traffic and look for a match.

Deprecation notice

Cloudflare Firewall Rules has been deprecated. Cloudflare has moved existing firewall rules to [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/). For more information on this change, refer to the [upgrade guide](https://developers.cloudflare.com/waf/reference/legacy/firewall-rules-upgrade/).

For example, a filter matching:

* An HTTP user agent, and
* The HTTP path, and
* The source IP address

Associate a filter with a firewall rule to define the scope of that rule.

Use IP lists within a filter to refer collectively to a group of IP addresses. Refer to the [Lists API](https://developers.cloudflare.com/waf/tools/lists/lists-api/) for more information.

Before getting started with the Cloudflare Filters API, familiarize yourself with rule [expressions](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/). For a complete reference, refer to [Rules language](https://developers.cloudflare.com/ruleset-engine/rules-language/).

## Differences from other Cloudflare APIs

The Firewall Rules API behaves differently from most Cloudflare APIs in two ways:

* API calls accept and return multiple items, and allow applying data changes to multiple items.
* Although API calls return the [standard response](https://developers.cloudflare.com/fundamentals/api/), the error object follows the [JSON API standard ↗](http://jsonapi.org/format/#errors), such that in an error condition, it is clear which item produced the error and why.

To get started, review [What is a filter?](https://developers.cloudflare.com/firewall/api/cf-filters/what-is-a-filter/), followed by the Cloudflare Filters [JSON object](https://developers.cloudflare.com/firewall/api/cf-firewall-rules/json-object/) and [Endpoints](https://developers.cloudflare.com/firewall/api/cf-firewall-rules/endpoints/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-filters/","name":"Cloudflare Filters API"}}]}
```

---

---
title: DELETE examples
description: Delete filters or rules with DELETE API requests.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# DELETE examples

## Delete multiple filters

This example deletes filters with IDs `{filter_id_1}` and `{filter_id_2}`.

Request

```

curl --request DELETE \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/filters?id={filter_id_1}&id={filter_id_2}" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>"


```

Response

```

{

  "result": [

    {

      "id": "<FILTER_ID_1>"

    },

    {

      "id": "<FILTER_ID_2>"

    }

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

## Delete a single filter

This example deletes a single filter with ID `{filter_id}`.

Request

```

curl --request DELETE \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/filters/{filter_id}" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>"


```

Response

```

{

  "result": [

    {

      "id": "<FILTER_ID>"

    }

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-filters/","name":"Cloudflare Filters API"}},{"@type":"ListItem","position":5,"item":{"@id":"/firewall/api/cf-filters/delete/","name":"DELETE examples"}}]}
```

---

---
title: Endpoints
description: API endpoints for managing filters and firewall rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Endpoints

To invoke a Cloudflare Filters API operation, append the endpoint to the Cloudflare API base URL:

```

https://api.cloudflare.com/client/v4/


```

For authentication instructions, refer to [Getting Started: Requests](https://developers.cloudflare.com/fundamentals/api/) in the Cloudflare API documentation.

For help with endpoints and pagination, refer to [Getting Started: Endpoints](https://developers.cloudflare.com/fundamentals/api/).

Note

The Filters API endpoints require a value for `<ZONE_ID>`.

To retrieve a list of zones associated with your account, use the [List Zones](https://developers.cloudflare.com/api/resources/zones/methods/list/) operation and note the Zone ID associated with the domain for which you want to manage filters.

The Cloudflare Filters API supports the operations outlined below. Visit the pages in this section for examples.

| Operation                                                                                        | Method & Endpoint                            | Notes                                                                                                                                                             |
| ------------------------------------------------------------------------------------------------ | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Create filters](https://developers.cloudflare.com/api/resources/filters/methods/create/)        | POST zones/<ZONE\_ID>/filters                | Handled as a single transaction. If there is an error, the entire operation fails.                                                                                |
| [Get filters](https://developers.cloudflare.com/api/resources/filters/methods/list/)             | GET zones/<ZONE\_ID>/filters                 | Lists all current filters. Results return paginated with 25 items per page by default. Use optional parameters to narrow results.                                 |
| [Get a filter](https://developers.cloudflare.com/api/resources/filters/methods/get/)             | GET zones/<ZONE\_ID>/filters/<FILTER\_ID>    | Retrieve a single filter by ID.                                                                                                                                   |
| [Update filters](https://developers.cloudflare.com/api/resources/filters/methods/bulk%5Fupdate/) | PUT zones/<ZONE\_ID>/filters                 | Handled as a single transaction. All filters must exist for operation to succeed. If there is an error, the entire operation fails.                               |
| [Update a filter](https://developers.cloudflare.com/api/resources/filters/methods/update/)       | PUT zones/<ZONE\_ID>/filters/<FILTER\_ID>    | Update a single filter by ID.                                                                                                                                     |
| [Delete filters](https://developers.cloudflare.com/api/resources/filters/methods/bulk%5Fdelete/) | DELETE zones/<ZONE\_ID>/filters              | Delete existing filters. Must specify list of filter IDs.Empty requests result in no deletion. Returns HTTP status code 200 if a specified filter does not exist. |
| [Delete a filter](https://developers.cloudflare.com/api/resources/filters/methods/delete/)       | DELETE zones/<ZONE\_ID>/filters/<FILTER\_ID> | Delete a filter by ID.                                                                                                                                            |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-filters/","name":"Cloudflare Filters API"}},{"@type":"ListItem","position":5,"item":{"@id":"/firewall/api/cf-filters/endpoints/","name":"Endpoints"}}]}
```

---

---
title: GET examples
description: Retrieve filters or rules with GET API requests.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# GET examples

## Get all filters

This example returns all filters in zone with ID `{zone_id}`.

Request

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/filters" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>"


```

Response

```

{

  "result": [

    {

      "id": "<FILTER_ID_1>",

      "paused": false,

      "description": "Login from office",

      "expression": "ip.src eq 93.184.216.0 and (http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")"

    },

    {

      "id": "<FILTER_ID_2>",

      "paused": false,

      "description": "Login",

      "expression": "(http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")"

    },

    {

      "id": "<FILTER_ID_3>",

      "paused": false,

      "description": "not /api",

      "expression": "not http.request.uri.path matches \"^/api/.*$\""

    },

    {

      "id": "<FILTER_ID_4>",

      "paused": false,

      "description": "/api",

      "expression": "http.request.uri.path matches \"^/api/.*$\""

    },

    {

      "id": "<FILTER_ID_5>",

      "paused": false,

      "expression": "ip.src eq 93.184.216.0"

    }

  ],

  "success": true,

  "errors": [],

  "messages": [],

  "result_info": {

    "page": 1,

    "per_page": 25,

    "count": 5,

    "total_count": 5,

    "total_pages": 1

  }

}


```

## Get by filter ID

This example returns the filter with ID `{filter_id}`.

Request

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/filters/{filter_id}" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>"


```

Response

```

{

  "result": {

    "id": "<FILTER_ID>",

    "paused": false,

    "description": "Login from office",

    "expression": "ip.src eq 93.184.216.0 and (http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-filters/","name":"Cloudflare Filters API"}},{"@type":"ListItem","position":5,"item":{"@id":"/firewall/api/cf-filters/get/","name":"GET examples"}}]}
```

---

---
title: JSON object
description: Review the JSON structure for filter and rule objects.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# JSON object

## Filter object structure and properties

A JSON response for the [Filters API](https://developers.cloudflare.com/api/resources/filters/methods/list/) has this structure:

```

{

  "id": "6f58318e7fa2477a23112e8118c66f61",

  "expression": "http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\"",

  "paused": true,

  "description": "WordPress login paths",

  "ref": ""

}


```

The following table summarizes the object properties:

| Property           | Description                                                                                                                                                                        | Constraints                            |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
| id String          | A UUIDv4 identifier generated by Cloudflare.                                                                                                                                       | Unique, read onlyLength: 32 characters |
| expression String  | A Rules language expression used to evaluate requests. For more information, refer to [Expressions](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/). |                                        |
| paused Boolean     | Returns true when the filter is not active. Use ref to enable/disable the filter.                                                                                                  | Default: false                         |
| description String | An informative summary of the filter.                                                                                                                                              | Maximum length: 500 characters         |
| ref String         | A short string for tagging filters.                                                                                                                                                | Maximum length: 50 characters          |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-filters/","name":"Cloudflare Filters API"}},{"@type":"ListItem","position":5,"item":{"@id":"/firewall/api/cf-filters/json-object/","name":"JSON object"}}]}
```

---

---
title: POST example
description: Create filters or rules with a POST API request.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# POST example

This example creates several filters using a single API call.

Request

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/filters" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data '[

  {

    "expression": "ip.src eq 93.184.216.0"

  },

  {

    "expression": "http.request.uri.path matches \"^/api/.*$\"",

    "description": "/api"

  },

  {

    "expression": "not http.request.uri.path matches \"^/api/.*$\"",

    "description": "not /api"

  },

  {

    "expression": "(http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")",

    "description": "Login"

  },

  {

    "expression": "ip.src eq 93.184.216.0 and (http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")",

    "description": "Login from office"

  }

]'


```

Response

```

{

  "result": [

    {

      "id": "<FILTER_ID_1>",

      "paused": false,

      "expression": "ip.src eq 93.184.216.0"

    },

    {

      "id": "<FILTER_ID_2>",

      "paused": false,

      "description": "/api",

      "expression": "http.request.uri.path matches \"^/api/.*$\""

    },

    {

      "id": "<FILTER_ID_3>",

      "paused": false,

      "description": "not /api",

      "expression": "not http.request.uri.path matches \"^/api/.*$\""

    },

    {

      "id": "<FILTER_ID_4>",

      "paused": false,

      "description": "Login",

      "expression": "(http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")"

    },

    {

      "id": "<FILTER_ID_5>",

      "paused": false,

      "description": "Login from office",

      "expression": "ip.src eq 93.184.216.0 and (http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")"

    }

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-filters/","name":"Cloudflare Filters API"}},{"@type":"ListItem","position":5,"item":{"@id":"/firewall/api/cf-filters/post/","name":"POST example"}}]}
```

---

---
title: PUT examples
description: Update filters or rules with PUT API requests.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# PUT examples

## Update multiple filters

This example updates two filters with IDs `<FILTER_ID_1>` and `<FILTER_ID_2>` using a single API call.

Request

```

curl --request PUT \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/filters" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data '[

  {

    "id": "<FILTER_ID_1>",

    "paused": false,

    "expression": "ip.src eq 93.184.216.0",

    "description": "IP of example.org"

  },

  {

    "id": "<FILTER_ID_2>",

    "expression": "http.request.uri.path matches \"^/api/.*$\"",

    "description": "/api"

  }

]'


```

Response

```

{

  "result": [

    {

      "id": "<FILTER_ID>",

      "paused": false,

      "description": "IP of example.org",

      "expression": "ip.src eq 93.184.216.0"

    },

    {

      "id": "<FILTER_ID_2>",

      "paused": false,

      "description": "/api",

      "expression": "http.request.uri.path matches \"^/api/.*$\""

    }

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

## Update a single filter

This example updates the filter with ID `{filter_id}`.

Request

```

curl --request PUT \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/filters/{filter_id}" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data '{

  "id": "<FILTER_ID>",

  "paused": false,

  "description": "Login from office",

  "expression": "ip.src in {2400:cb00::/32 2a06:98c0::/29} and (http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")"

}'


```

Response

```

{

  "result": {

    "id": "<FILTER_ID>",

    "paused": false,

    "description": "Login from office",

    "expression": "ip.src in {2400:cb00::/32 2a06:98c0::/29} and (http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")"

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-filters/","name":"Cloudflare Filters API"}},{"@type":"ListItem","position":5,"item":{"@id":"/firewall/api/cf-filters/put/","name":"PUT examples"}}]}
```

---

---
title: Expression validation
description: Validate firewall rule expressions via the API.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Expression validation

The Cloudflare Filters API supports an endpoint for validating expressions.

## Examples

### Validate expression via query string

Request

```

curl "https://api.cloudflare.com/client/v4/filters/validate-expr?expression=ip.src==34" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>"


```

Response

```

{

  "result": null,

  "success": false,

  "errors": [

    {

      "message": "Filter parsing error:\n`ip.src==34`\n          ^^ couldn't parse address in network: invalid IP address syntax\n"

    }

  ],

  "messages": null

}


```

Note the validation error in the response. In this example, the error is due to an invalid IP address format:

```

Filter parsing error:

`ip.src==34`

          ^^ couldn't parse address in network: invalid IP address syntax


```

### Validate expression via JSON object

Request

```

curl "https://api.cloudflare.com/client/v4/filters/validate-expr" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data '{

  "expression": "ip.src in {2400:cb00::/32 2405:8100::/2000 2c0f:f248::/32 2a06:98c0::/29}"

}'


```

Response

```

{

  "result": null,

  "success": false,

  "errors": [

    {

      "message": "Filter parsing error:\n`ip.src in {2400:cb00::/32 2405:8100::/2000 2c0f:f248::/32 2a06:98c0::/29}`\n                                        ^^^^ number too large to fit in target type while parsing with radix 10\n"

    }

  ],

  "messages": null

}


```

Note the validation error in the response. In this example, the value for the subnet mask, `/2000`, is not a valid IPv6 CIDR mask:

```

Filter parsing error:

`ip.src in {2400:cb00::/32 2405:8100::/2000 2c0f:f248::/32 2a06:98c0::/29}`

                                       ^^^^ number too large to fit in target type while parsing with radix 10


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-filters/","name":"Cloudflare Filters API"}},{"@type":"ListItem","position":5,"item":{"@id":"/firewall/api/cf-filters/validation/","name":"Expression validation"}}]}
```

---

---
title: What is a filter?
description: A filter is a way of setting up if (traffic matches certain criteria), then do something.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# What is a filter?

A filter is a way of saying:

```

if (traffic matches certain criteria) then...


```

A filter contains an expression that would return `true` or `false` when evaluated against traffic passing through Cloudflare.

Filter expressions are human and machine readable, and you can compose complex logic to precisely match the traffic that you are interested in detecting and acting upon.

A filter object typically looks like the following:

```

{

  "id": "<FILTER_ID>",

  "expression": "(http.request.uri.path ~ \"^.*wp-login.php$\" or http.request.uri.path ~ \"^.*xmlrpc.php$\") and ip.src ne 93.184.216.34",

  "description": "WordPress login paths via the login page or mobile RPC endpoint"

}


```

The expression specified in this example filter is:

```

(http.request.uri.path ~ "^.*wp-login.php$" or http.request.uri.path ~ "^.*xmlrpc.php$") and ip.src ne 93.184.216.34


```

This filter expression has a `(this or that) and not this` structure designed to:

* Capture two WordPress paths that may be subject to brute force password attacks, and
* Exclude traffic that comes from the IP address `93.184.216.34`.

Imagine that this is an IP for your office. This expression demonstrates a filter that might be used (in a firewall rule) to block access to the WordPress login when accessed outside the office network.

For more information on rule expressions, refer to [Expressions](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/) in the Rules language documentation.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-filters/","name":"Cloudflare Filters API"}},{"@type":"ListItem","position":5,"item":{"@id":"/firewall/api/cf-filters/what-is-a-filter/","name":"What is a filter?"}}]}
```

---

---
title: Firewall Rules API
description: Manage firewall rules via the Firewall Rules API.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Firewall Rules API

Use the Firewall Rules API to programmatically manage your rules.

Deprecation notice

Cloudflare Firewall Rules has been deprecated. Cloudflare has moved existing firewall rules to [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/). For more information on this change, refer to the [upgrade guide](https://developers.cloudflare.com/waf/reference/legacy/firewall-rules-upgrade/).

When working with the Firewall Rules API, refer to these topics for additional context:

* [Firewall rules actions](https://developers.cloudflare.com/firewall/cf-firewall-rules/actions/)
* [Cloudflare Filters API](https://developers.cloudflare.com/firewall/api/cf-filters/)

To get started with the API, review the Firewall Rules API [JSON object](https://developers.cloudflare.com/firewall/api/cf-firewall-rules/json-object/) and [Endpoints](https://developers.cloudflare.com/firewall/api/cf-firewall-rules/endpoints/).

For more information on the Rules language used to write rule expressions, refer to [Rules language](https://developers.cloudflare.com/ruleset-engine/rules-language/) in the Ruleset Engine documentation.

## Differences from other Cloudflare APIs

The Firewall Rules API behaves differently from most Cloudflare APIs in two ways:

* API calls accept and return multiple items, and allow applying data changes to multiple items.
* Although API calls return the [standard response](https://developers.cloudflare.com/fundamentals/api/), the error object follows the [JSON API standard ↗](http://jsonapi.org/format/#errors), such that in an error condition, it is clear which item produced the error and why.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-firewall-rules/","name":"Firewall Rules API"}}]}
```

---

---
title: DELETE examples
description: Delete filters or rules with DELETE API requests.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# DELETE examples

Note

The `DELETE` operation does not delete any filter related to the firewall rule. To delete the filter, use the [Filters API](https://developers.cloudflare.com/firewall/api/cf-filters/).

## Delete multiple rules

This example deletes firewall rules with IDs `{rule_id_1}` and `{rule_id_2}`.

Request

```

curl --request DELETE \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/firewall/rules?id={rule_id_1}&id={rule_id_2}" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>"


```

Response

```

{

  "result": [

    {

      "id": "<RULE_ID_1>"

    },

    {

      "id": "<RULE_ID_2>"

    }

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

## Delete a single rule

This example deletes the rule with ID `{rule_id}`.

Request

```

curl --request DELETE \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/firewall/rules/{rule_id}" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>"


```

Response

```

{

  "result": [

    {

      "id": "<RULE_ID>"

    }

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-firewall-rules/","name":"Firewall Rules API"}},{"@type":"ListItem","position":5,"item":{"@id":"/firewall/api/cf-firewall-rules/delete/","name":"DELETE examples"}}]}
```

---

---
title: Endpoints
description: API endpoints for managing filters and firewall rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Endpoints

To invoke a Cloudflare Firewall Rules API operation, append the endpoint to the Cloudflare API base URL:

```

https://api.cloudflare.com/client/v4/


```

For authentication instructions, refer to [Getting Started: Requests](https://developers.cloudflare.com/fundamentals/api/) in the Cloudflare API documentation.

For help with endpoints and pagination, refer to [Getting Started: Endpoints](https://developers.cloudflare.com/fundamentals/api/).

Note

The Firewall Rules API endpoints require a value for `<ZONE_ID>`.

To retrieve a list of zones associated with your account, use the [List Zones](https://developers.cloudflare.com/api/resources/zones/methods/list/) operation and note the zone ID associated with the domain whose firewall rules you want to manage.

The Cloudflare Firewall Rules API supports the operations outlined below. Visit the pages in this section for examples.

| Operation                                                                                                                   | Method & Endpoint                                 | Notes                                                                                                                                                                         |
| --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Create firewall rules](https://developers.cloudflare.com/api/resources/firewall/subresources/rules/methods/create/)        | POST zones/<ZONE\_ID>/firewall/rules              | Handled as a single transaction. If there is an error, the entire operation fails.                                                                                            |
| [List firewall rules](https://developers.cloudflare.com/api/resources/firewall/subresources/rules/methods/list/)            | GET zones/<ZONE\_ID>/firewall/rules               | Lists all current firewall rules. Results return paginated with 25 items per page by default. Use optional parameters to narrow results.                                      |
| [Get a firewall rule](https://developers.cloudflare.com/api/resources/firewall/subresources/rules/methods/get/)             | GET zones/<ZONE\_ID>/firewall/rules/<RULE\_ID>    | Retrieve a single firewall rule by ID.                                                                                                                                        |
| [Update firewall rules](https://developers.cloudflare.com/api/resources/firewall/subresources/rules/methods/bulk%5Fupdate/) | PUT zones/<ZONE\_ID>/firewall/rules               | Handled as a single transaction. All rules must exist for operation to succeed. If there is an error, the entire operation fails.                                             |
| [Update a firewall rule](https://developers.cloudflare.com/api/resources/firewall/subresources/rules/methods/update/)       | PUT zones/<ZONE\_ID>/firewall/rules/<RULE\_ID>    | Update a single firewall rule by ID.                                                                                                                                          |
| [Delete firewall rules](https://developers.cloudflare.com/api/resources/firewall/subresources/rules/methods/bulk%5Fdelete/) | DELETE zones/<ZONE\_ID>/firewall/rules            | Delete existing firewall rules. Must specify list of firewall rule IDs.Empty requests result in no deletion. Returns HTTP status code 200 if a specified rule does not exist. |
| [Delete a firewall rule](https://developers.cloudflare.com/api/resources/firewall/subresources/rules/methods/delete/)       | DELETE zones/<ZONE\_ID>/firewall/rules/<RULE\_ID> | Delete a firewall rule by ID.                                                                                                                                                 |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-firewall-rules/","name":"Firewall Rules API"}},{"@type":"ListItem","position":5,"item":{"@id":"/firewall/api/cf-firewall-rules/endpoints/","name":"Endpoints"}}]}
```

---

---
title: GET examples
description: Retrieve filters or rules with GET API requests.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# GET examples

## Get all rules

This example returns all the firewall rules in the zone with ID `{zone_id}`.

Request

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/firewall/rules" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>"


```

Response

```

{

  "result": [

    {

      "id": "<RULE_ID_1>",

      "paused": false,

      "description": "allow API traffic without challenge",

      "action": "allow",

      "priority": null,

      "filter": {

        "id": "<FILTER_ID_1>",

        "expression": "http.request.uri.path matches \"^/api/.*$\"",

        "paused": false,

        "description": "/api"

      }

    },

    {

      "id": "<RULE_ID_2>",

      "paused": false,

      "description": "do not challenge login from office",

      "action": "allow",

      "priority": null,

      "filter": {

        "id": "<FILTER_ID_2>",

        "expression": "ip.src in {2400:cb00::/32 2803:f800::/32 2c0f:f248::/32 2a06:98c0::/29} and (http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")",

        "paused": false,

        "description": "Login from office"

      }

    },

    {

      "id": "<RULE_ID_3>",

      "paused": false,

      "description": "challenge login",

      "action": "challenge",

      "priority": null,

      "filter": {

        "id": "<FILTER_ID_3>",

        "expression": "(http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")",

        "paused": false,

        "description": "Login"

      }

    },

    {

      "id": "<RULE_ID_4>",

      "paused": false,

      "description": "Non-interactive challenge site",

      "action": "js_challenge",

      "priority": null,

      "filter": {

        "id": "<FILTER_ID_4>",

        "expression": "not http.request.uri.path matches \"^/api/.*$\"",

        "paused": false,

        "description": "not /api"

      }

    }

  ],

  "success": true,

  "errors": [],

  "messages": [],

  "result_info": {

    "page": 1,

    "per_page": 25,

    "count": 4,

    "total_count": 4,

    "total_pages": 1

  }

}


```

## Get rule by ID

This example returns the firewall rule with ID `{rule_id}`.

Request

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/firewall/rules/{rule_id}" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>"


```

Response

```

{

  "result": {

    "id": "<RULE_ID>",

    "paused": false,

    "description": "do not challenge login from office",

    "action": "allow",

    "priority": null,

    "filter": {

      "id": "<FILTER_ID>",

      "expression": "ip.src in {2400:cb00::/32 2803:f800::/32 2c0f:f248::/32 2a06:98c0::/29} and (http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")",

      "paused": false,

      "description": "Login from office"

    }

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-firewall-rules/","name":"Firewall Rules API"}},{"@type":"ListItem","position":5,"item":{"@id":"/firewall/api/cf-firewall-rules/get/","name":"GET examples"}}]}
```

---

---
title: JSON object
description: Review the JSON structure for filter and rule objects.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# JSON object

## Firewall rule example JSON response

A JSON response for the [Firewall Rules API](https://developers.cloudflare.com/api/resources/firewall/subresources/rules/methods/list/) has this structure:

```

{

  "id": "772bf1026a72c400ea576db1ffa16407",

  "filter": {

    "id": "6f58318e7fa2477a23112e8118c66f61",

    "expression": "http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\"",

    "paused": false,

    "description": "WordPress login paths",

    "ref": ""

  },

  "action": "challenge",

  "priority": 1000,

  "paused": false,

  "description": "Protect blog login page",

  "ref": ""

}


```

This table summarizes the object properties:

| Name               | Description                                                                                                                                                                                                                               | Constraints                                                                                                                              |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| id String          | A UUIDv4 identifier generated by Cloudflare.                                                                                                                                                                                              | Unique, read onlyLength: 32 characters                                                                                                   |
| filter Object      | A [Cloudflare Filter object](https://developers.cloudflare.com/firewall/api/cf-filters/json-object/) that contains an expression for evaluating this rule.                                                                                |                                                                                                                                          |
| action String      | The action to take when a request satisfies the filter expression for this rule.                                                                                                                                                          | Refer to [Firewall rules actions](https://developers.cloudflare.com/firewall/cf-firewall-rules/actions/) for a list of supported values. |
| priority Number    | Determines the order of evaluation for the rule relative to others. Lower values indicate greater priority. Rules without a value are evaluated last. For guidance, refer to [Avoiding priority conflicts](#avoiding-priority-conflicts). | Read onlyMaximum length: 32                                                                                                              |
| paused Boolean     | Returns true when the rule is not active. Use ref to enable/disable the rule.                                                                                                                                                             | Default: false                                                                                                                           |
| description String | An informative summary of the rule.                                                                                                                                                                                                       | Maximum length: 500 characters                                                                                                           |
| ref String         | A short string for tagging rules.                                                                                                                                                                                                         | Maximum length: 50 characters                                                                                                            |

## Avoiding priority conflicts

Priority plays a key role in configuring firewall rules. With Cloudflare Filters, it is possible to construct conflicting rules such as:

* Allow requests from the office IP range, and
* Block requests with a specific user agent.

Requests from the office IP range using the user agent to block would trigger both rules, but we cannot both allow and block the request. To solve this problem, firewall rules follows a strict ordering depending on action and priority.

Cloudflare prioritizes rules in descending order, such that priority 1 is first and rules with no priority are last. For rules of equal priority, Cloudflare orders them by action according to their [order of precedence](https://developers.cloudflare.com/firewall/cf-firewall-rules/actions/#supported-actions). In the example above, if no priority is set, the rule `allow request from the office IP range` would apply because the _allow_ action has a higher precedence than _block_.

To reduce the risk of unintended behavior, it is best to explicitly specify the desired priority for potentially conflicting rules.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-firewall-rules/","name":"Firewall Rules API"}},{"@type":"ListItem","position":5,"item":{"@id":"/firewall/api/cf-firewall-rules/json-object/","name":"JSON object"}}]}
```

---

---
title: POST example
description: Create filters or rules with a POST API request.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# POST example

This example creates several firewall rules using a single API call.

Note

To create a firewall rule you need a [filter](https://developers.cloudflare.com/firewall/api/cf-filters/what-is-a-filter/) identifier (`id`). If you have not created a filter yet, refer to the [Cloudflare Filters API documentation](https://developers.cloudflare.com/firewall/api/cf-filters/).

Request

```

curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/firewall/rules" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data '[

  {

    "filter": {

      "id": "<FILTER_ID_1>"

    },

    "action": "allow",

    "description": "Do not challenge login from office"

  },

  {

    "filter": {

      "id": "<FILTER_ID_2>"

    },

    "action": "challenge",

    "description": "Challenge login"

  },

  {

    "filter": {

      "id": "<FILTER_ID_3>"

    },

    "action": "js_challenge",

    "description": "Non-interactive challenge site"

  },

  {

    "filter": {

      "id": "<FILTER_ID_4>"

    },

    "action": "allow",

    "description": "Allow API traffic without challenge"

  }

]'


```

Response

```

{

  "result": [

    {

      "id": "<RULE_ID_1>",

      "paused": false,

      "description": "Do not challenge login from office",

      "action": "allow",

      "priority": null,

      "filter": {

        "id": "<FILTER_ID_1>",

        "expression": "ip.src in {2400:cb00::/32 2803:f800::/32 2c0f:f248::/32 2a06:98c0::/29} and (http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")",

        "paused": false,

        "description": "Login from office"

      }

    },

    {

      "id": "<RULE_ID_2>",

      "paused": false,

      "description": "Challenge login",

      "action": "challenge",

      "priority": null,

      "filter": {

        "id": "<FILTER_ID_2>",

        "expression": "(http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")",

        "paused": false,

        "description": "Login"

      }

    },

    {

      "id": "<RULE_ID_3>",

      "paused": false,

      "description": "Non-interactive challenge site",

      "action": "js_challenge",

      "priority": null,

      "filter": {

        "id": "<FILTER_ID_3>",

        "expression": "not http.request.uri.path matches \"^/api/.*$\"",

        "paused": false,

        "description": "not /api"

      }

    },

    {

      "id": "<RULE_ID_4>",

      "paused": false,

      "description": "Allow API traffic without challenge",

      "action": "allow",

      "priority": null,

      "filter": {

        "id": "<FILTER_ID_4>",

        "expression": "http.request.uri.path matches \"^/api/.*$\"",

        "paused": false,

        "description": "/api"

      }

    }

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-firewall-rules/","name":"Firewall Rules API"}},{"@type":"ListItem","position":5,"item":{"@id":"/firewall/api/cf-firewall-rules/post/","name":"POST example"}}]}
```

---

---
title: PUT examples
description: Update filters or rules with PUT API requests.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# PUT examples

## Update multiple rules

This example updates several firewall rules using a single API call.

You can include up to 25 rules in the JSON object array (`-d` flag) to update as a batch. The batch is handled as a transaction.

Request

```

curl --request PUT \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/firewall/rules" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data '[

  {

    "id": "<RULE_ID>",

    "paused": false,

    "description": "Challenge site",

    "action": "challenge",

    "priority": null,

    "filter": {

      "id": "<FILTER_ID>",

      "expression": "not http.request.uri.path matches \"^/api/.*$\"",

      "paused": false,

      "description": "not /api"

    }

  }

]'


```

Note

`PUT` does not update the filter specified. It only looks at the filter ID (`<FILTER_ID>`) to update the rule with a new filter.

To update the filter, use the [Filters API](https://developers.cloudflare.com/firewall/api/cf-filters/).

Response

```

{

  "result": [

    {

      "id": "<RULE_ID>",

      "paused": false,

      "description": "Challenge site",

      "action": "challenge",

      "priority": null,

      "filter": {

        "id": "<FILTER_ID>",

        "expression": "not http.request.uri.path matches \"^/api/.*$\"",

        "paused": false,

        "description": "not /api"

      }

    }

  ],

  "success": true,

  "errors": [],

  "messages": []

}


```

## Update a single rule

This example updates the firewall rule with ID `{rule_id}`.

You must include the following fields in the request body:

* `id`
* `action`
* `filter.id`

All other fields are optional.

Request

```

curl --request PUT \

"https://api.cloudflare.com/client/v4/zones/{zone_id}/firewall/rules/{rule_id}" \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data '{

  "id": "<RULE_ID>",

  "paused": false,

  "description": "Do not challenge login from office IPv6",

  "action": "allow",

  "priority": null,

  "filter": {

    "id": "<FILTER_ID>",

    "expression": "ip.src in {2400:cb00::/32 2803:f800::/32 2c0f:f248::/32 2a06:98c0::/29} and (http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")",

    "paused": false,

    "description": "Login from office"

  }

}'


```

Response

```

{

  "result": {

    "id": "<RULE_ID>",

    "paused": false,

    "description": "Do not challenge login from office IPv6",

    "action": "allow",

    "priority": null,

    "filter": {

      "id": "<FILTER_ID>",

      "expression": "ip.src in {2400:cb00::/32 2803:f800::/32 2c0f:f248::/32 2a06:98c0::/29} and (http.request.uri.path ~ \"^.*/wp-login.php$\" or http.request.uri.path ~ \"^.*/xmlrpc.php$\")",

      "paused": false,

      "description": "Login from office"

    }

  },

  "success": true,

  "errors": [],

  "messages": []

}


```

Note

`PUT` overwrites fields that are not explicitly passed in the request.

For example, if the request omits `description`, any previously existing `description` value will be erased.

To preserve existing values, issue a `GET` request and based on the response, determine which fields (and respective values) to include in your `PUT` request.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/api/","name":"Manage rules via the APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/api/cf-firewall-rules/","name":"Firewall Rules API"}},{"@type":"ListItem","position":5,"item":{"@id":"/firewall/api/cf-firewall-rules/put/","name":"PUT examples"}}]}
```

---

---
title: Required firewall rule changes to enable URL normalization
description: Update firewall rules for URL normalization.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/firewall/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Required firewall rule changes to enable URL normalization

Deprecation notice

Cloudflare Firewall Rules has been deprecated. Cloudflare has moved existing firewall rules to [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/). For more information on this change, refer to the [upgrade guide](https://developers.cloudflare.com/waf/reference/legacy/firewall-rules-upgrade/).

On 2021-04-08, Cloudflare announced [URL normalization](https://developers.cloudflare.com/rules/normalization/), a feature that protects zones by normalizing HTTP request URI paths.

Malicious users can craft specific URIs that could be interpreted differently by firewall systems and origin systems. When you enable **Normalize incoming URLs**, all rules filtering on the URI path will receive the URL in a canonical form, which provides an extra layer of protection against these malicious users.

Cloudflare gradually enabled URL normalization for all Cloudflare zones except for those that could be impacted by this change. We determined the impacted zones by analyzing all firewall rules, looking for patterns in HTTP fields that would no longer match when using URL normalization techniques.

These fields are the following:

* `http.request.uri.path`
* `http.request.full_uri`
* `http.request.uri`

Cloudflare did not enable URL normalization automatically for zones that would be impacted by these changes to prevent any change in behavior of your existing firewall rules.

## Why URL normalization is important

Cloudflare strongly recommends that you enable **Normalize incoming URLs** in **Rules** \> **Overview** \> **URL Normalization** to strengthen your zone's security posture. Not doing so leaves your zone at greater risk of a successful attack. Malicious parties could craft the URL in a way that the rules are not accounting for.

For example, a firewall rule with an expression such as `http.request.uri.path contains "/login"` could be bypassed if the malicious actor has encoded the `l` character as `%6C`. In this scenario, and with URL normalization disabled, traffic would not be matched by the firewall rule.

Refer to [How URL normalization works](https://developers.cloudflare.com/rules/normalization/how-it-works/) for more information and additional examples.

---

## Recommended procedure

It is recommended that you:

1. Update any firewall rules impacted by the URL normalization changes.
2. Enable URL normalization.

These steps will ensure a stronger security posture on your zone(s).

### 1\. Review and update firewall rules

Before enabling URL normalization, you should review the affected firewall rules on your zone(s) and take one of the following approaches:

* Edit these firewall rules to remove the parts which will no longer trigger once normalized — for example, any rules that look for `//` or `../` in URL paths. Administrators previously created these rules to perform a limited URL normalization, and these rules can now be safely disabled and then deleted.
* If you wish to identify visitors with non-normalized URI paths with these firewall rules, you should update them to use the original (or raw) non-normalized fields. These fields are the following:  
   * `raw.http.request.uri.path`  
   * `raw.http.request.full_uri`  
   * `raw.http.request.uri`

### 2\. Enable URL normalization

Once you have updated the affected firewall rules, enable URL normalization in **Rules** \> **Overview** \> **URL Normalization**.

A Cloudflare user must have the [Firewall role](https://developers.cloudflare.com/fundamentals/manage-members/roles/) or one of the Administrator roles to access URL normalization settings in the dashboard.

---

## Related resources

* [URL normalization](https://developers.cloudflare.com/rules/normalization/)
* [Transform Rules](https://developers.cloudflare.com/rules/transform/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/firewall/","name":"Firewall Rules (deprecated)"}},{"@type":"ListItem","position":3,"item":{"@id":"/firewall/troubleshooting/","name":"Troubleshooting"}},{"@type":"ListItem","position":4,"item":{"@id":"/firewall/troubleshooting/required-changes-to-enable-url-normalization/","name":"Required firewall rule changes to enable URL normalization"}}]}
```

---

---
title: Key Transparency Auditor
description: Secure public key distribution in end-to-end encrypted messaging systems.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/key-transparency/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Key Transparency Auditor

Secure the distribution of public keys in your end-to-end encrypted (E2EE) messaging systems

Cloudflare's Key Transparency Auditor aims to secure the distribution of public keys for end-to-end encrypted (E2EE) messaging systems like [WhatsApp ↗](https://engineering.fb.com/2023/04/13/security/whatsapp-key-transparency/). It achieves this by building a verifiable append-only data structure called a Log, similar to [Certificate Transparency ↗](https://developer.mozilla.org/en-US/docs/Web/Security/Certificate%5FTransparency).

Cloudflare acts as an auditor of Key Transparency Logs to ensure the transparency of end-to-end encrypted messaging public keys. Cloudflare provides an API for anyone to monitor the verification work we perform, and verify the state of its associated Logs locally.

## Related products

**[Certificate Transparency Monitoring](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/certificate-transparency-monitoring/)** 

Certificate Transparency (CT) Monitoring is an opt-in feature in public beta that aims to improve security by allowing you to double-check any SSL/TLS certificates issued for your domain.

**[Privacy Gateway](https://developers.cloudflare.com/privacy-gateway/)** 

Privacy Gateway is a managed service deployed on Cloudflare's global network that implements part of the [Oblivious HTTP (OHTTP) IETF ↗](https://www.ietf.org/archive/id/draft-thomson-http-oblivious-01.html) standard. The goal of Privacy Gateway and Oblivious HTTP is to hide the client's IP address when interacting with an application backend.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/key-transparency/","name":"Key Transparency Auditor"}}]}
```

---

---
title: Monitor the Auditor
description: Verify Key Transparency audit proofs locally using the Plexi CLI tool.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/key-transparency/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Monitor the Auditor

Cloudflare's Key Transparency Auditor validates Log audit proofs and provides a signature for them. The Log can then distribute these signatures to its end-users, and provides users with confidence that keys have not been tampered with.

In order to verify our work, you can use [Plexi ↗](https://github.com/cloudflare/plexi), a CLI tool that allows anyone to perform proof verification locally via a public [API](https://developers.cloudflare.com/key-transparency/api/).

## Features

* Verify authenticity of a signature, to confirm it has been signed by a given public key
* Verify the validity of [facebook/akd ↗](https://github.com/facebook/akd) proofs
* List Logs an Auditor monitors

## Installation

| Environment                                                     | CLI Command         |
| --------------------------------------------------------------- | ------------------- |
| [Cargo ↗](https://www.rust-lang.org/tools/install) (Rust 1.81+) | cargo install plexi |

## Usage

Use the `--help` option for more details about the commands and their options.

Terminal window

```

plexi [OPTIONS] <COMMAND>


```

### Configure your auditor remote

`plexi` does not come with a default remote auditor, and you will need to choose your own.

You can do so either by passing `--remote-url=<REMOTE>` or setting the `PLEXI_REMOTE_URL` environment variable.

A common remote is provided below:

| Name       | Remote                                        |
| ---------- | --------------------------------------------- |
| Cloudflare | https://plexi.key-transparency.cloudflare.com |

If you have deployed your own auditor, you can add a remote by filing a [GitHub issue ↗](https://github.com/cloudflare/plexi/issues).

### List monitored Logs

An auditor monitors multiple Logs at once. To discover which Logs an auditor is monitoring, run the following:

Terminal window

```

plexi ls --remote-url 'https://plexi.key-transparency.cloudflare.com'

whatsapp.key-transparency.v1


```

### Audit a signature

The Key Transparency Auditor vouches for Log validity by ensuring epoch uniqueness and verifying the associated proof.

`plexi audit` provides information about a given epoch and its validity. It can perform a local audit to confirm the auditor behaviour.

For instance, to verify WhatsApp Log auditted by Cloudflare Auditor, run the following:

Terminal window

```

> plexi audit --remote-url 'https://plexi.key-transparency.cloudflare.com' --namespace 'whatsapp.key-transparency.v1' --long

Namespace

  Name               : whatsapp.key-transparency.v1

  Ciphersuite        : ed25519(protobuf)


Signature (2024-09-23T16:53:45Z)

  Epoch height        : 489193

  Epoch digest        : cbe5097ae832a3ae51ad866104ffd4aa1f7479e873fd18df9cb96a02fc91ebfe

  Signature           : fe94973e19da826487b637c019d3ce52f0c08093ada00b4fe6563e2f8117b4345121342bc33aae249be47979dfe704478e2c18aed86e674df9f934b718949c08

  Signature verification: success

  Proof verification  : success


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/key-transparency/","name":"Key Transparency Auditor"}},{"@type":"ListItem","position":3,"item":{"@id":"/key-transparency/monitor-the-auditor/","name":"Monitor the Auditor"}}]}
```

---

---
title: Auditor
description: Retrieve auditor public keys and verify epoch signatures.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/key-transparency/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Auditor

The Auditor is designed to sign epoch information, which includes the time at which the request is received by the Auditor, the epoch number, and the epoch digest. The Auditor serializes this information in binary using protobuf or bincode and checks whether the requested inclusion is valid, as in it satisfies [publication constraints](https://developers.cloudflare.com/key-transparency/api/epochs/#constraints).

If the Log is setup to provide [AKD ↗](https://github.com/facebook/akd) audit proof, the Auditor verifies them asynchronously.

## Get Auditor information

`keys` contain Auditor public keys which allow for key rotation later.

Terminal window

```

curl 'https://plexi.key-transparency.cloudflare.com/info'

{

  "keys": [

    {

      "public_key": "d1036a33a8731e82a29dc68210988b32b60b7c1bd22d2341f2e339f4db3a2f4a",

      "not_before": 1712311441501

    }

  ],

  "logs": [

    "508607faff7cb16be841e901eca41a6239461f239e7e610c9ea2576f334bc144"

  ]

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/key-transparency/","name":"Key Transparency Auditor"}},{"@type":"ListItem","position":3,"item":{"@id":"/key-transparency/api/","name":"API"}},{"@type":"ListItem","position":4,"item":{"@id":"/key-transparency/api/auditor-information/","name":"Auditor"}}]}
```

---

---
title: Epochs
description: Query epoch digests, audit proofs, and publication constraints.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/key-transparency/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Epochs

## Get an epoch

Terminal window

```

curl 'https://plexi.key-transparency.cloudflare.com/namespaces/{namespace}/audits/1'

{

  "namespace": "your.new.log.com",

  "timestamp": 1717084639921,

  "epoch": 1,

  "digest": "1111111111111111111111111111111111111111111111111111111111111111",

  "signature": "f6a51443bb6703813b330959d9d97471bc06464142165e59733fa102a18b052782a5307d59c31b8b13c1af7dfff6f6e7bf44e880d44e26e96c50a72f72a30c07"

}


```

## Publish a new epoch

Refer to the example below to publish a new epoch by requesting its signature.

This API is authenticated via [mTLS ↗](https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/), so that only a Log owner can publish new epochs.

Terminal window

```

curl 'https://plexi.key-transparency.cloudflare.com/namespaces/{namespace}/audits' \

      --header 'Content-Type: application/json' \

      --data '{"epoch": 1, "digest": "1111111111111111111111111111111111111111111111111111111111111111"}'

{

  "namespace": "your.new.log.com",

  "timestamp": 1717084639921,

  "epoch": 1,

  "digest": "1111111111111111111111111111111111111111111111111111111111111111",

  "signature": "f6a51443bb6703813b330959d9d97471bc06464142165e59733fa102a18b052782a5307d59c31b8b13c1af7dfff6f6e7bf44e880d44e26e96c50a72f72a30c07",

  "key_id": 74,

}


```

### Constraints

* If `root` is defined for the namespace, the first epoch must match it (number and digest).
* Epochs must be increasing. Second epoch is 2, third is 3, etc.
* Epochs must have a unique digest or it will be rejected.
* Epochs cannot be republished.
* Digest must be a 32 byte string hex encoded (length 64).

If a namespace is disabled, you receive the following error:

```

HTTP 400 Bad Request

Namespace is disabled and read-only.


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/key-transparency/","name":"Key Transparency Auditor"}},{"@type":"ListItem","position":3,"item":{"@id":"/key-transparency/api/","name":"API"}},{"@type":"ListItem","position":4,"item":{"@id":"/key-transparency/api/epochs/","name":"Epochs"}}]}
```

---

---
title: Namespaces
description: Create and manage namespaces representing logs monitored by the Cloudflare Auditor.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/key-transparency/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Namespaces

The Cloudflare Key Transparency API is organized in namespaces, each one representing a Log monitored by Cloudflare Auditor. If you want to register a namespace, contact us.

## Create a namespace

The following fields are required when making a `POST` request:

* `name`
* `public`
* `root`
* `signature_version`:  
   * 0x0001 for [Protobuf serialisation ↗](https://github.com/cloudflare/plexi/blob/main/plexi%5Fcore/src/proto/specs/types.proto) Ed25519 signature from the Auditor  
   * 0x0002 for [bincode serialisation ↗](https://github.com/bincode-org/bincode/blob/trunk/docs/spec.md) E25519 serialisation by the Auditor

The `log_directory` field is optional. If set, Cloudflare will use it to fetch audit proofs and validate them.

This API is authenticated via [mTLS ↗](https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/).

Terminal window

```

curl 'https://plexi.key-transparency.cloudflare.com/namespaces' \

          --header 'Content-Type: application/json' \

          --data '{

   "name": "your.new.log.com",

   "root": "1/1111111111111111111111111111111111111111111111111111111111111111",

   "log_directory": "https://your.new.log.com/path/to/proofs",

  "signature_version": 1

  }'

{

  "name": "your.new.log.com",

  "log_directory": "https://your.new.log.com/path/to/proofs",

  "root": "1/1111111111111111111111111111111111111111111111111111111111111111",

  "status": "Initialization",

  "reports_uri": "/namespaces/your.new.log.com/reports",

  "audits_uri": "/namespaces/your.new.log.com/audits",

  "signature_version": 1

}


```

After publishing the first epoch, `status` will show `Online`. Possible statuses include:

* `Online`
* `Initialization`
* `Disabled`

## List all namespaces

Refer to the example below to get information about all public namespaces.

Terminal window

```

curl 'https://plexi.key-transparency.cloudflare.com/namespaces'

{

   "namespaces": [

       { "name": "your.new.log.com", "root": "1/abc", "reports_uri": "/namespaces/your.new.log.com/reports", "audits_uri": "/namespaces/your.new.log.com/audits", "log_directory": "https://your.new.log.com/path/to/proofs", "status": "online" },

       { "name": "my.new.log.com", "reports_uri": "/namespaces/meta-bt-2024/reports", "audits_uri": "/namespaces/meta-bt-2024/audits", "status": "initialization" }

   ]

}


```

## Disable a namespace

If a log state has been corrupted, lost, or needs to be sharded to be maintainable, the Auditor allows the Log operator to mark a namespace as `Disabled`.

This API is authenticated via [mTLS ↗](https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/).

Terminal window

```

curl -X PATCH 'https://plexi.key-transparency.cloudflare.com/namespaces/{namespace}' \

          -H 'Content-Type: application/json' \

          -d '{

   "status": "Disabled"

  }'

{

  "name": "your.new.log.com",

  "log_directory": "https://your.new.log.com/path/to/proofs",

  "root": "1/1111111111111111111111111111111111111111111111111111111111111111",

  "status": "Disabled",

  "reports_uri": "/namespaces/your.new.log.com/reports",

  "audits_uri": "/namespaces/your.new.log.com/audits",

  "signature_version": 1

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/key-transparency/","name":"Key Transparency Auditor"}},{"@type":"ListItem","position":3,"item":{"@id":"/key-transparency/api/","name":"API"}},{"@type":"ListItem","position":4,"item":{"@id":"/key-transparency/api/namespaces/","name":"Namespaces"}}]}
```

---

---
title: Cloudflare Secrets Store
description: Use Secrets Store to encrypt and store sensitive information as secrets that are securely reusable across your Cloudflare account.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/secrets-store/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Cloudflare Secrets Store

Encrypt and store sensitive information as secrets that are securely reusable across your account.

 Available in open beta 

Cloudflare Secrets Store is a secure, centralized location in which account-level secrets are stored and managed. The secrets are securely encrypted and stored across all [Cloudflare data centers ↗](https://www.cloudflare.com/network/).

Secrets Store is currently compatible with [Cloudflare Workers](https://developers.cloudflare.com/secrets-store/integrations/workers/) and [AI Gateway](https://developers.cloudflare.com/ai-gateway/configuration/bring-your-own-keys/). Integrations with other products will be added in the future.

China availability

Secrets Store is unavailable in the [Cloudflare China Network](https://developers.cloudflare.com/china-network/), operated by Cloudflare's partner JD Cloud.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/secrets-store/","name":"Secrets Store"}}]}
```

---

---
title: Secrets Store access control
description: Learn about role-based access control with Cloudflare Secrets Store
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/secrets-store/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Secrets Store access control

Secrets Store allows security administrators to have more control by implementing role-based access. For details about roles at Cloudflare, refer to [Fundamentals](https://developers.cloudflare.com/fundamentals/manage-members/).

Availability

While all Cloudflare accounts will have access to the Secrets Store section on the dashboard, only users with the necessary permissions will be able to interact with it, as described below.

## Relevant roles

Refer to the list below for default role definitions.

#### Super Administrator

* Can create, edit, duplicate, delete, and view secrets metadata.
* Can [add a Secrets Store binding to a Worker](https://developers.cloudflare.com/secrets-store/integrations/workers/).
* Can [create an association between a secret and an AI gateway](https://developers.cloudflare.com/ai-gateway/configuration/bring-your-own-keys/).

#### Secrets Store Admin

* Can create, edit, duplicate, delete, and view secrets metadata.

#### Secrets Store Deployer

* Can view secrets metadata but cannot create, edit, duplicate, nor delete secrets.
* Can [add a Secrets Store binding to a Worker](https://developers.cloudflare.com/secrets-store/integrations/workers/).
* Can [create an association between a secret and an AI gateway](https://developers.cloudflare.com/ai-gateway/configuration/bring-your-own-keys/).

#### Secrets Store Reporter

* Can view secrets metadata.
* Cannot perform any actions (create, edit, duplicate, delete secrets), nor use Secrets Store integrations with other Cloudflare products.

## API token permissions

The following API token permissions can also be used to grant access to Secrets Store resources.

* **Account Secrets Store Edit**: Allows a user to create, edit, duplicate, or delete secrets.
* **Account Secrets Store Read**: Allows a user to view secrets metadata.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/secrets-store/","name":"Secrets Store"}},{"@type":"ListItem","position":3,"item":{"@id":"/secrets-store/access-control/","name":"Secrets Store access control"}}]}
```

---

---
title: Manage account secrets
description: Learn about different operations to manage your secrets in Cloudflare Secrets Store.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/secrets-store/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Manage account secrets

Secrets can be API tokens, public/private keys, authorization keys, passwords, or even code variables. The only limitation is that a secret must be a string that does not exceed 1024 bytes.

Once a secret is added to the Secrets Store, it can no longer be decrypted or accessed via API or on the dashboard. Only the service associated with a given secret will be able to access it.

## Limits

Customers who create a secrets store in the open beta can have up to 100 secrets per account. Also, there can only be one store per account.

Production secrets

If you use [Wrangler](https://developers.cloudflare.com/secrets-store/manage-secrets/how-to/#manage-via-wrangler), there is a difference between production secrets and secrets that are only created locally (without the `--remote` flag). The limit of 100 secrets per account only considers production secrets.

## Resources

* [Manage via Wrangler](https://developers.cloudflare.com/workers/wrangler/commands/secrets-store/#secrets-store-secret)
* [Create a secret](https://developers.cloudflare.com/secrets-store/manage-secrets/how-to/#create-a-secret)
* [Duplicate a secret](https://developers.cloudflare.com/secrets-store/manage-secrets/how-to/#duplicate-a-secret)
* [Edit a secret](https://developers.cloudflare.com/secrets-store/manage-secrets/how-to/#edit-a-secret)
* [Delete a secret](https://developers.cloudflare.com/secrets-store/manage-secrets/how-to/#delete-a-secret)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/secrets-store/","name":"Secrets Store"}},{"@type":"ListItem","position":3,"item":{"@id":"/secrets-store/manage-secrets/","name":"Manage account secrets"}}]}
```

---

---
title: How to
description: Create, update, duplicate, and delete secrets using the dashboard, API, or Wrangler.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/secrets-store/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# How to

Refer to the sections below to learn about common actions you might want to take when managing your data in Secrets Store.

You must have a [Super Administrator or Secrets Store Admin role](https://developers.cloudflare.com/secrets-store/access-control/) within your Cloudflare account.

## Manage via Wrangler

[Wrangler](https://developers.cloudflare.com/workers/wrangler/) is a command-line interface (CLI) that allows you to manage [Cloudflare Workers](https://developers.cloudflare.com/workers/) projects. Refer to [Wrangler commands](https://developers.cloudflare.com/workers/wrangler/commands/secrets-store/#secrets-store-secret) for guidance on how to use it with Secrets Store.

## Create a secret

* [ Dashboard ](#tab-panel-10387)
* [ API ](#tab-panel-10388)

1. In the Cloudflare dashboard, go to the **Secrets Store** page.  
[ Go to **Secrets Store** ](https://dash.cloudflare.com/?to=/:account/secrets-store)
2. Select **Create secret**.
3. Fill in the required fields. Note that, once the secret is saved, the secret value will no longer be available for viewing.
4. (Optional) Select **Add additional secret** to create more than one secret at a time.
5. Select **Save** to confirm.

Note

A secret `name` cannot contain spaces. Refer to [Secrets Store API](https://developers.cloudflare.com/api/resources/secrets%5Fstore/) for the full API documentation.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Secrets Store Write`

Create a secret

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores/$STORE_ID/secrets" \

  --request POST \

  --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \

  --header "X-Auth-Key: $CLOUDFLARE_API_KEY" \

  --json '[

    {

        "name": "<MY_SECRET_NAME>",

        "value": "<SECRET_VALUE>",

        "scopes": [

            "workers"

        ],

        "comment": ""

    },

    {

        "name": "<MY_SECRET_NAME_2>",

        "value": "<SECRET_VALUE>",

        "scopes": [

            "workers"

        ],

        "comment": ""

    }

  ]'


```

## Duplicate a secret

Duplicate a secret to keep the same secret value but change name, scope, or comments.

* [ Dashboard ](#tab-panel-10381)
* [ API ](#tab-panel-10382)

1. In the Cloudflare dashboard, go to the **Secrets Store** page.  
[ Go to **Secrets Store** ](https://dash.cloudflare.com/?to=/:account/secrets-store)
2. Search for the secret you would like to duplicate within the existing secrets list.
3. Select the three dots next to the secret and choose **Duplicate**.
4. Edit the **Secret name**, **Permission scope**, or **Comment**, according to your needs.
5. Select **Save** to confirm.

Note

A secret `name` cannot contain spaces. Refer to [Secrets Store API](https://developers.cloudflare.com/api/resources/secrets%5Fstore/) for the full API documentation.

Terminal window

```

curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores/$STORE_ID/secrets/$SECRET_ID/duplicate \

--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

--header "Content-Type: application/json" \

--data '{

    "name":"<NEW_DUPLICATE_NAME>",

    "scopes":["workers"],

    "comment":""

}'


```

## Edit a secret

Edit a secret to replace an existing value with a new one.

Warning

This action will cause the replacement in all services using the secret.

You can also edit the secret **Permission scope** and **Comment**.

* [ Dashboard ](#tab-panel-10383)
* [ API ](#tab-panel-10384)

1. In the Cloudflare dashboard, go to the **Secrets Store** page.  
[ Go to **Secrets Store** ](https://dash.cloudflare.com/?to=/:account/secrets-store)
2. Search for the secret you would like to edit within the existing secrets list.
3. Select the three dots next to the secret and choose **Edit**.
4. Edit the available fields according to your needs and select **Save** to confirm.

Refer to [Secrets Store API](https://developers.cloudflare.com/api/resources/secrets%5Fstore/) for the full API documentation.

Terminal window

```

curl --request PATCH \

https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores/$STORE_ID/secrets/$SECRET_ID \

--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

--header "Content-Type: application/json" \

--data '{

    "comment":"<NEW_COMMENT>",

    "value":"<NEW_SECRET_VALUE>",

    "scopes":["workers"]

}'


```

## Delete a secret

Warning

Before deleting a secret, make sure it is not deployed in your [Workers applications ↗](https://dash.cloudflare.com/?to=/:account/workers-and-pages/) or [AI gateways ↗](https://dash.cloudflare.com/?to=/:account/ai/ai-gateway).

* [ Dashboard ](#tab-panel-10385)
* [ API ](#tab-panel-10386)

1. In the Cloudflare dashboard, go to the **Secrets Store** page.  
[ Go to **Secrets Store** ](https://dash.cloudflare.com/?to=/:account/secrets-store)
2. Search for the secret you would like to delete within the existing secrets list.
3. Select the three dots next to the secret and choose **Delete**.
4. Type in the secret name and select **Delete** to confirm.

Refer to [Secrets Store API](https://developers.cloudflare.com/api/resources/secrets%5Fstore/) for the full API documentation.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Secrets Store Write`

Delete a secret

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores/$STORE_ID/secrets/$SECRET_ID" \

  --request DELETE \

  --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \

  --header "X-Auth-Key: $CLOUDFLARE_API_KEY"


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/secrets-store/","name":"Secrets Store"}},{"@type":"ListItem","position":3,"item":{"@id":"/secrets-store/manage-secrets/","name":"Manage account secrets"}},{"@type":"ListItem","position":4,"item":{"@id":"/secrets-store/manage-secrets/how-to/","name":"How to"}}]}
```

---

---
title: Audit logs
description: Actions logged for Secrets Store operations, including create, update, and delete.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/secrets-store/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Audit logs

[Audit logs](https://developers.cloudflare.com/fundamentals/account/account-security/review-audit-logs/) provide a comprehensive summary of changes made within your Cloudflare account. This page lists the actions that are logged for Secrets Store.

* Access
* Create  
   * Duplicating a secret is presented as a `create` log with a field `duplicated_from_id`.
* Update  
   * A boolean `"value_modified": true` is presented when the secret value is edited.
* Delete

For information on how to access and use audit logs, refer to [Fundamentals](https://developers.cloudflare.com/fundamentals/account/account-security/review-audit-logs/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/secrets-store/","name":"Secrets Store"}},{"@type":"ListItem","position":3,"item":{"@id":"/secrets-store/audit-logs/","name":"Audit logs"}}]}
```

---

# Secrets Store

# Stores

## List account stores

**get** `/accounts/{account_id}/secrets_store/stores`

Lists all the stores in an account

### Path Parameters

- `account_id: string`

  Account Identifier

### Query Parameters

- `direction: optional "asc" or "desc"`

  Direction to sort objects

  - `"asc"`

  - `"desc"`

- `order: optional "name" or "comment" or "created" or 2 more`

  Order secrets by values in the given field

  - `"name"`

  - `"comment"`

  - `"created"`

  - `"modified"`

  - `"status"`

- `page: optional number`

  Page number

- `per_page: optional number`

  Number of objects to return per page

### Returns

- `errors: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

- `result: optional array of object { id, created, modified, 2 more }`

  - `id: string`

    Store Identifier

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the store

  - `account_id: optional string`

    Account Identifier

- `result_info: optional object { count, page, per_page, 2 more }`

  - `count: optional number`

    Total number of results for the requested service.

  - `page: optional number`

    Current page within paginated list of results.

  - `per_page: optional number`

    Number of results per page of results.

  - `total_count: optional number`

    Total results available without any search parameters.

  - `total_pages: optional number`

    The number of total pages in the entire result set.

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores \
    -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
    -H "X-Auth-Key: $CLOUDFLARE_API_KEY"
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "success": true,
  "result": [
    {
      "id": "023e105f4ecef8ad9ca31a8372d0c353",
      "created": "2023-09-21T18:56:32.624632Z",
      "modified": "2023-09-21T18:56:32.624632Z",
      "name": "service_x_keys",
      "account_id": "985e105f4ecef8ad9ca31a8372d0c353"
    }
  ],
  "result_info": {
    "count": 1,
    "page": 1,
    "per_page": 20,
    "total_count": 2000,
    "total_pages": 100
  }
}
```

## Get a store by ID

**get** `/accounts/{account_id}/secrets_store/stores/{store_id}`

Returns details of a single store

### Path Parameters

- `account_id: string`

  Account Identifier

- `store_id: string`

  Store Identifier

### Returns

- `errors: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

- `result: optional object { id, created, modified, 2 more }`

  - `id: string`

    Store Identifier

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the store

  - `account_id: optional string`

    Account Identifier

- `result_info: optional object { count, page, per_page, 2 more }`

  - `count: optional number`

    Total number of results for the requested service.

  - `page: optional number`

    Current page within paginated list of results.

  - `per_page: optional number`

    Number of results per page of results.

  - `total_count: optional number`

    Total results available without any search parameters.

  - `total_pages: optional number`

    The number of total pages in the entire result set.

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores/$STORE_ID \
    -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
    -H "X-Auth-Key: $CLOUDFLARE_API_KEY"
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "success": true,
  "result": {
    "id": "023e105f4ecef8ad9ca31a8372d0c353",
    "created": "2023-09-21T18:56:32.624632Z",
    "modified": "2023-09-21T18:56:32.624632Z",
    "name": "service_x_keys",
    "account_id": "985e105f4ecef8ad9ca31a8372d0c353"
  },
  "result_info": {
    "count": 1,
    "page": 1,
    "per_page": 20,
    "total_count": 2000,
    "total_pages": 100
  }
}
```

## Create a store

**post** `/accounts/{account_id}/secrets_store/stores`

Creates a store in the account

### Path Parameters

- `account_id: string`

  Account Identifier

### Body Parameters

- `name: string`

  The name of the store

### Returns

- `errors: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

- `result: optional object { id, created, modified, 2 more }`

  - `id: string`

    Store Identifier

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the store

  - `account_id: optional string`

    Account Identifier

- `result_info: optional object { count, page, per_page, 2 more }`

  - `count: optional number`

    Total number of results for the requested service.

  - `page: optional number`

    Current page within paginated list of results.

  - `per_page: optional number`

    Number of results per page of results.

  - `total_count: optional number`

    Total results available without any search parameters.

  - `total_pages: optional number`

    The number of total pages in the entire result set.

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores \
    -H 'Content-Type: application/json' \
    -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
    -H "X-Auth-Key: $CLOUDFLARE_API_KEY" \
    -d '{
          "name": "service_x_keys"
        }'
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "success": true,
  "result": {
    "id": "023e105f4ecef8ad9ca31a8372d0c353",
    "created": "2023-09-21T18:56:32.624632Z",
    "modified": "2023-09-21T18:56:32.624632Z",
    "name": "service_x_keys",
    "account_id": "985e105f4ecef8ad9ca31a8372d0c353"
  },
  "result_info": {
    "count": 1,
    "page": 1,
    "per_page": 20,
    "total_count": 2000,
    "total_pages": 100
  }
}
```

## Delete a store

**delete** `/accounts/{account_id}/secrets_store/stores/{store_id}`

Deletes a single store. By default, a store that still contains secrets
cannot be deleted and returns HTTP 409 (Conflict) with the "store_not_empty"
error. Pass `force=true` to cascade-delete all secrets in the store.
Empty stores are always deleted regardless of the force parameter.

### Path Parameters

- `account_id: string`

  Account Identifier

- `store_id: string`

  Store Identifier

### Query Parameters

- `force: optional boolean`

  When true, cascade-deletes all secrets in the store before deleting
  the store itself. Required when deleting a non-empty store. Without
  this parameter, attempting to delete a non-empty store returns 409.

### Returns

- `errors: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

- `result: optional unknown`

  Result is null for delete operations.

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores/$STORE_ID \
    -X DELETE \
    -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
    -H "X-Auth-Key: $CLOUDFLARE_API_KEY"
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "success": true,
  "result": {}
}
```

## Domain Types

### Store List Response

- `StoreListResponse object { id, created, modified, 2 more }`

  - `id: string`

    Store Identifier

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the store

  - `account_id: optional string`

    Account Identifier

### Store Get Response

- `StoreGetResponse object { id, created, modified, 2 more }`

  - `id: string`

    Store Identifier

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the store

  - `account_id: optional string`

    Account Identifier

### Store Create Response

- `StoreCreateResponse object { id, created, modified, 2 more }`

  - `id: string`

    Store Identifier

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the store

  - `account_id: optional string`

    Account Identifier

### Store Delete Response

- `StoreDeleteResponse = unknown`

  Result is null for delete operations.

# Secrets

## List store secrets

**get** `/accounts/{account_id}/secrets_store/stores/{store_id}/secrets`

Lists all store secrets

### Path Parameters

- `account_id: string`

  Account Identifier

- `store_id: string`

  Store Identifier

### Query Parameters

- `direction: optional "asc" or "desc"`

  Direction to sort objects

  - `"asc"`

  - `"desc"`

- `order: optional "name" or "comment" or "created" or 2 more`

  Order secrets by values in the given field

  - `"name"`

  - `"comment"`

  - `"created"`

  - `"modified"`

  - `"status"`

- `page: optional number`

  Page number

- `per_page: optional number`

  Number of objects to return per page

- `scopes: optional array of array of string`

  Only secrets with the given scopes will be returned

- `search: optional string`

  Search secrets using a filter string, filtering across name and comment

### Returns

- `errors: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

- `result: optional array of object { id, created, modified, 5 more }`

  - `id: string`

    Secret identifier tag.

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the secret

  - `status: "pending" or "active" or "deleted"`

    - `"pending"`

    - `"active"`

    - `"deleted"`

  - `store_id: string`

    Store Identifier

  - `comment: optional string`

    Freeform text describing the secret

  - `scopes: optional array of string`

    The list of services that can use this secret.

- `result_info: optional object { count, page, per_page, 2 more }`

  - `count: optional number`

    Total number of results for the requested service.

  - `page: optional number`

    Current page within paginated list of results.

  - `per_page: optional number`

    Number of results per page of results.

  - `total_count: optional number`

    Total results available without any search parameters.

  - `total_pages: optional number`

    The number of total pages in the entire result set.

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores/$STORE_ID/secrets \
    -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
    -H "X-Auth-Key: $CLOUDFLARE_API_KEY"
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "success": true,
  "result": [
    {
      "id": "3fd85f74b32742f1bff64a85009dda07",
      "created": "2023-09-21T18:56:32.624632Z",
      "modified": "2023-09-21T18:56:32.624632Z",
      "name": "MY_API_KEY",
      "status": "pending",
      "store_id": "023e105f4ecef8ad9ca31a8372d0c353",
      "comment": "info about my secret",
      "scopes": [
        "workers",
        "ai_gateway",
        "dex",
        "access"
      ]
    }
  ],
  "result_info": {
    "count": 1,
    "page": 1,
    "per_page": 20,
    "total_count": 2000,
    "total_pages": 100
  }
}
```

## Get a secret by ID

**get** `/accounts/{account_id}/secrets_store/stores/{store_id}/secrets/{secret_id}`

Returns details of a single secret

### Path Parameters

- `account_id: string`

  Account Identifier

- `store_id: string`

  Store Identifier

- `secret_id: string`

  Secret identifier tag.

### Returns

- `errors: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

- `result: optional object { id, created, modified, 5 more }`

  - `id: string`

    Secret identifier tag.

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the secret

  - `status: "pending" or "active" or "deleted"`

    - `"pending"`

    - `"active"`

    - `"deleted"`

  - `store_id: string`

    Store Identifier

  - `comment: optional string`

    Freeform text describing the secret

  - `scopes: optional array of string`

    The list of services that can use this secret.

- `result_info: optional object { count, page, per_page, 2 more }`

  - `count: optional number`

    Total number of results for the requested service.

  - `page: optional number`

    Current page within paginated list of results.

  - `per_page: optional number`

    Number of results per page of results.

  - `total_count: optional number`

    Total results available without any search parameters.

  - `total_pages: optional number`

    The number of total pages in the entire result set.

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores/$STORE_ID/secrets/$SECRET_ID \
    -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
    -H "X-Auth-Key: $CLOUDFLARE_API_KEY"
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "success": true,
  "result": {
    "id": "3fd85f74b32742f1bff64a85009dda07",
    "created": "2023-09-21T18:56:32.624632Z",
    "modified": "2023-09-21T18:56:32.624632Z",
    "name": "MY_API_KEY",
    "status": "pending",
    "store_id": "023e105f4ecef8ad9ca31a8372d0c353",
    "comment": "info about my secret",
    "scopes": [
      "workers",
      "ai_gateway",
      "dex",
      "access"
    ]
  },
  "result_info": {
    "count": 1,
    "page": 1,
    "per_page": 20,
    "total_count": 2000,
    "total_pages": 100
  }
}
```

## Create a secret

**post** `/accounts/{account_id}/secrets_store/stores/{store_id}/secrets`

Creates a secret in the account

### Path Parameters

- `account_id: string`

  Account Identifier

- `store_id: string`

  Store Identifier

### Body Parameters

- `body: array of object { name, scopes, value, comment }`

  - `name: string`

    The name of the secret

  - `scopes: array of string`

    The list of services that can use this secret.

  - `value: string`

    The value of the secret. Maximum 64 KiB (65,536 bytes). Note that this is 'write only' - no API response will provide this value, it is only used to create/modify secrets.

  - `comment: optional string`

    Freeform text describing the secret

### Returns

- `errors: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

- `result: optional array of object { id, created, modified, 5 more }`

  - `id: string`

    Secret identifier tag.

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the secret

  - `status: "pending" or "active" or "deleted"`

    - `"pending"`

    - `"active"`

    - `"deleted"`

  - `store_id: string`

    Store Identifier

  - `comment: optional string`

    Freeform text describing the secret

  - `scopes: optional array of string`

    The list of services that can use this secret.

- `result_info: optional object { count, page, per_page, 2 more }`

  - `count: optional number`

    Total number of results for the requested service.

  - `page: optional number`

    Current page within paginated list of results.

  - `per_page: optional number`

    Number of results per page of results.

  - `total_count: optional number`

    Total results available without any search parameters.

  - `total_pages: optional number`

    The number of total pages in the entire result set.

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores/$STORE_ID/secrets \
    -H 'Content-Type: application/json' \
    -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
    -H "X-Auth-Key: $CLOUDFLARE_API_KEY" \
    -d '[
          {
            "name": "MY_API_KEY",
            "scopes": [
              "workers",
              "ai_gateway",
              "dex",
              "access"
            ],
            "value": "api-token-secret-123",
            "comment": "info about my secret"
          }
        ]'
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "success": true,
  "result": [
    {
      "id": "3fd85f74b32742f1bff64a85009dda07",
      "created": "2023-09-21T18:56:32.624632Z",
      "modified": "2023-09-21T18:56:32.624632Z",
      "name": "MY_API_KEY",
      "status": "pending",
      "store_id": "023e105f4ecef8ad9ca31a8372d0c353",
      "comment": "info about my secret",
      "scopes": [
        "workers",
        "ai_gateway",
        "dex",
        "access"
      ]
    }
  ],
  "result_info": {
    "count": 1,
    "page": 1,
    "per_page": 20,
    "total_count": 2000,
    "total_pages": 100
  }
}
```

## Patch a secret

**patch** `/accounts/{account_id}/secrets_store/stores/{store_id}/secrets/{secret_id}`

Updates a single secret

### Path Parameters

- `account_id: string`

  Account Identifier

- `store_id: string`

  Store Identifier

- `secret_id: string`

  Secret identifier tag.

### Body Parameters

- `comment: optional string`

  Freeform text describing the secret

- `scopes: optional array of string`

  The list of services that can use this secret.

- `value: optional string`

  The value of the secret. Maximum 64 KiB (65,536 bytes). Note that this is 'write only' - no API response will provide this value, it is only used to create/modify secrets.

### Returns

- `errors: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

- `result: optional object { id, created, modified, 5 more }`

  - `id: string`

    Secret identifier tag.

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the secret

  - `status: "pending" or "active" or "deleted"`

    - `"pending"`

    - `"active"`

    - `"deleted"`

  - `store_id: string`

    Store Identifier

  - `comment: optional string`

    Freeform text describing the secret

  - `scopes: optional array of string`

    The list of services that can use this secret.

- `result_info: optional object { count, page, per_page, 2 more }`

  - `count: optional number`

    Total number of results for the requested service.

  - `page: optional number`

    Current page within paginated list of results.

  - `per_page: optional number`

    Number of results per page of results.

  - `total_count: optional number`

    Total results available without any search parameters.

  - `total_pages: optional number`

    The number of total pages in the entire result set.

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores/$STORE_ID/secrets/$SECRET_ID \
    -X PATCH \
    -H 'Content-Type: application/json' \
    -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
    -H "X-Auth-Key: $CLOUDFLARE_API_KEY" \
    -d '{
          "comment": "info about my secret",
          "scopes": [
            "workers",
            "ai_gateway",
            "dex",
            "access"
          ],
          "value": "api-token-secret-123"
        }'
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "success": true,
  "result": {
    "id": "3fd85f74b32742f1bff64a85009dda07",
    "created": "2023-09-21T18:56:32.624632Z",
    "modified": "2023-09-21T18:56:32.624632Z",
    "name": "MY_API_KEY",
    "status": "pending",
    "store_id": "023e105f4ecef8ad9ca31a8372d0c353",
    "comment": "info about my secret",
    "scopes": [
      "workers",
      "ai_gateway",
      "dex",
      "access"
    ]
  },
  "result_info": {
    "count": 1,
    "page": 1,
    "per_page": 20,
    "total_count": 2000,
    "total_pages": 100
  }
}
```

## Delete a secret

**delete** `/accounts/{account_id}/secrets_store/stores/{store_id}/secrets/{secret_id}`

Deletes a single secret

### Path Parameters

- `account_id: string`

  Account Identifier

- `store_id: string`

  Store Identifier

- `secret_id: string`

  Secret identifier tag.

### Returns

- `errors: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

- `result: optional unknown`

  Result is null for delete operations.

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores/$STORE_ID/secrets/$SECRET_ID \
    -X DELETE \
    -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
    -H "X-Auth-Key: $CLOUDFLARE_API_KEY"
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "success": true,
  "result": {}
}
```

## Delete secrets

**delete** `/accounts/{account_id}/secrets_store/stores/{store_id}/secrets`

Deletes one or more secrets

### Path Parameters

- `account_id: string`

  Account Identifier

- `store_id: string`

  Store Identifier

### Returns

- `errors: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

- `result: optional unknown`

  Result is null for delete operations.

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores/$STORE_ID/secrets \
    -X DELETE \
    -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
    -H "X-Auth-Key: $CLOUDFLARE_API_KEY"
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "success": true,
  "result": {}
}
```

## Duplicate Secret

**post** `/accounts/{account_id}/secrets_store/stores/{store_id}/secrets/{secret_id}/duplicate`

Duplicates the secret, keeping the value

### Path Parameters

- `account_id: string`

  Account Identifier

- `store_id: string`

  Store Identifier

- `secret_id: string`

  Secret identifier tag.

### Body Parameters

- `name: string`

  The name of the secret

- `scopes: array of string`

  The list of services that can use this secret.

- `comment: optional string`

  Freeform text describing the secret

### Returns

- `errors: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

- `result: optional object { id, created, modified, 5 more }`

  - `id: string`

    Secret identifier tag.

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the secret

  - `status: "pending" or "active" or "deleted"`

    - `"pending"`

    - `"active"`

    - `"deleted"`

  - `store_id: string`

    Store Identifier

  - `comment: optional string`

    Freeform text describing the secret

  - `scopes: optional array of string`

    The list of services that can use this secret.

- `result_info: optional object { count, page, per_page, 2 more }`

  - `count: optional number`

    Total number of results for the requested service.

  - `page: optional number`

    Current page within paginated list of results.

  - `per_page: optional number`

    Number of results per page of results.

  - `total_count: optional number`

    Total results available without any search parameters.

  - `total_pages: optional number`

    The number of total pages in the entire result set.

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores/$STORE_ID/secrets/$SECRET_ID/duplicate \
    -H 'Content-Type: application/json' \
    -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
    -H "X-Auth-Key: $CLOUDFLARE_API_KEY" \
    -d '{
          "name": "MY_API_KEY",
          "scopes": [
            "workers",
            "ai_gateway",
            "dex",
            "access"
          ],
          "comment": "info about my secret"
        }'
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "success": true,
  "result": {
    "id": "3fd85f74b32742f1bff64a85009dda07",
    "created": "2023-09-21T18:56:32.624632Z",
    "modified": "2023-09-21T18:56:32.624632Z",
    "name": "MY_API_KEY",
    "status": "pending",
    "store_id": "023e105f4ecef8ad9ca31a8372d0c353",
    "comment": "info about my secret",
    "scopes": [
      "workers",
      "ai_gateway",
      "dex",
      "access"
    ]
  },
  "result_info": {
    "count": 1,
    "page": 1,
    "per_page": 20,
    "total_count": 2000,
    "total_pages": 100
  }
}
```

## Domain Types

### Secret List Response

- `SecretListResponse object { id, created, modified, 5 more }`

  - `id: string`

    Secret identifier tag.

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the secret

  - `status: "pending" or "active" or "deleted"`

    - `"pending"`

    - `"active"`

    - `"deleted"`

  - `store_id: string`

    Store Identifier

  - `comment: optional string`

    Freeform text describing the secret

  - `scopes: optional array of string`

    The list of services that can use this secret.

### Secret Get Response

- `SecretGetResponse object { id, created, modified, 5 more }`

  - `id: string`

    Secret identifier tag.

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the secret

  - `status: "pending" or "active" or "deleted"`

    - `"pending"`

    - `"active"`

    - `"deleted"`

  - `store_id: string`

    Store Identifier

  - `comment: optional string`

    Freeform text describing the secret

  - `scopes: optional array of string`

    The list of services that can use this secret.

### Secret Create Response

- `SecretCreateResponse object { id, created, modified, 5 more }`

  - `id: string`

    Secret identifier tag.

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the secret

  - `status: "pending" or "active" or "deleted"`

    - `"pending"`

    - `"active"`

    - `"deleted"`

  - `store_id: string`

    Store Identifier

  - `comment: optional string`

    Freeform text describing the secret

  - `scopes: optional array of string`

    The list of services that can use this secret.

### Secret Edit Response

- `SecretEditResponse object { id, created, modified, 5 more }`

  - `id: string`

    Secret identifier tag.

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the secret

  - `status: "pending" or "active" or "deleted"`

    - `"pending"`

    - `"active"`

    - `"deleted"`

  - `store_id: string`

    Store Identifier

  - `comment: optional string`

    Freeform text describing the secret

  - `scopes: optional array of string`

    The list of services that can use this secret.

### Secret Delete Response

- `SecretDeleteResponse = unknown`

  Result is null for delete operations.

### Secret Bulk Delete Response

- `SecretBulkDeleteResponse = unknown`

  Result is null for delete operations.

### Secret Duplicate Response

- `SecretDuplicateResponse object { id, created, modified, 5 more }`

  - `id: string`

    Secret identifier tag.

  - `created: string`

    Whenthe secret was created.

  - `modified: string`

    When the secret was modified.

  - `name: string`

    The name of the secret

  - `status: "pending" or "active" or "deleted"`

    - `"pending"`

    - `"active"`

    - `"deleted"`

  - `store_id: string`

    Store Identifier

  - `comment: optional string`

    Freeform text describing the secret

  - `scopes: optional array of string`

    The list of services that can use this secret.

# Quota

## View secret usage

**get** `/accounts/{account_id}/secrets_store/quota`

Lists the number of secrets used in the account.

### Path Parameters

- `account_id: string`

  Account Identifier

### Returns

- `errors: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

- `result: optional object { secrets }`

  - `secrets: object { quota, usage }`

    - `quota: number`

      The number of secrets the account is entitlted to use

    - `usage: number`

      The number of secrets the account is currently using

- `result_info: optional object { count, page, per_page, 2 more }`

  - `count: optional number`

    Total number of results for the requested service.

  - `page: optional number`

    Current page within paginated list of results.

  - `per_page: optional number`

    Number of results per page of results.

  - `total_count: optional number`

    Total results available without any search parameters.

  - `total_pages: optional number`

    The number of total pages in the entire result set.

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/quota \
    -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
    -H "X-Auth-Key: $CLOUDFLARE_API_KEY"
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "success": true,
  "result": {
    "secrets": {
      "quota": 10,
      "usage": 10
    }
  },
  "result_info": {
    "count": 1,
    "page": 1,
    "per_page": 20,
    "total_count": 2000,
    "total_pages": 100
  }
}
```

## Domain Types

### Quota Get Response

- `QuotaGetResponse object { secrets }`

  - `secrets: object { quota, usage }`

    - `quota: number`

      The number of secrets the account is entitlted to use

    - `usage: number`

      The number of secrets the account is currently using

---

---
title: BYOK (Store Keys)
description: Securely store AI provider API keys in AI Gateway and reference them in your gateway configuration.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ai-gateway/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# BYOK (Store Keys)

## Introduction

Bring your own keys (BYOK) is a feature in Cloudflare AI Gateway that allows you to securely store your AI provider API keys directly in the Cloudflare dashboard. Instead of including API keys in every request to your AI models, you can configure them once in the dashboard, and reference them in your gateway configuration.

The keys are stored securely with [Secrets Store](https://developers.cloudflare.com/secrets-store/) and allows for:

* Secure storage and limit exposure
* Easier key rotation
* Rate limit, budget limit and other restrictions with [Dynamic Routes](https://developers.cloudflare.com/ai-gateway/features/dynamic-routing/)

## Setting up BYOK

### Prerequisites

* Ensure your gateway is [authenticated](https://developers.cloudflare.com/ai-gateway/configuration/authentication/).
* Ensure you have appropriate [permissions](https://developers.cloudflare.com/secrets-store/access-control/) to create and deploy secrets on Secrets Store.

### Configure API keys

You can configure BYOK from the dashboard or by using the API.

#### Dashboard

When you add a provider key from the dashboard, AI Gateway creates and names the Secrets Store secret automatically.

1. Log into the [Cloudflare dashboard ↗](https://dash.cloudflare.com/) and select your account.
2. Go to **AI** \> **AI Gateway**.
3. Select your gateway or create a new one.
4. Go to the **Provider Keys** section.
5. Click **Add API Key**.
6. Select your AI provider from the dropdown.
7. Enter your API key and optionally provide a description.
8. Click **Save**.

#### API

If you use the API to configure BYOK, create the Secrets Store secret before you create the provider configuration. Name the secret with this format:

```

{gateway_id}_{provider_slug}_{alias}


```

For example, for gateway `my-gateway`, provider `anthropic`, and alias `default`, create the Secrets Store secret as:

```

my-gateway_anthropic_default


```

Then create the provider configuration with the same `provider_slug` and `alias` values.

The `secret_id` returned by Secrets Store is not used by AI Gateway for runtime lookup, so API-created secrets must follow the naming convention.

### Update your applications

Once you've configured your API keys in the dashboard:

1. **Remove API keys from your code**: Delete any hardcoded API keys or environment variables.
2. **Update request headers**: Remove provider authorization headers from your requests. Note that you still need to pass `cf-aig-authorization`.
3. **Test your integration**: Verify that requests work without including API keys.

## Example

With BYOK enabled, your workflow changes from:

1. **Traditional approach**: Include API key in every request header  
Terminal window  
```  
curl https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/openai/chat/completions \  
  -H 'cf-aig-authorization: Bearer {CF_AIG_TOKEN}' \  
  -H "Authorization: Bearer YOUR_OPENAI_API_KEY" \  
  -H "Content-Type: application/json" \  
  -d '{"model": "gpt-4", "messages": [...]}'  
```
2. **BYOK approach**: Configure key once in dashboard, make requests without exposing keys  
Terminal window  
```  
curl https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/openai/chat/completions \  
  -H 'cf-aig-authorization: Bearer {CF_AIG_TOKEN}' \  
  -H "Content-Type: application/json" \  
  -d '{"model": "gpt-4", "messages": [...]}'  
```

## Managing API keys

### Viewing configured keys

In the AI Gateway dashboard, you can:

* View all configured API keys by provider
* See when each key was last used
* Check the status of each key (active, expired, invalid)

### Rotating keys

To rotate an API key:

1. Generate a new API key from your AI provider
2. In the Cloudflare dashboard, edit the existing key entry
3. Replace the old key with the new one
4. Save the changes

Your applications will immediately start using the new key without any code changes or downtime.

### Revoking access

To remove an API key:

1. In the AI Gateway dashboard, find the key you want to remove
2. Click the **Delete** button
3. Confirm the deletion

Impact of key deletion

Deleting an API key will immediately stop all requests that depend on it. Make sure to update your applications or configure alternative keys before deletion.

## Multiple keys per provider

AI Gateway supports storing multiple API keys for the same provider. This allows you to:

* Use different keys for different use cases (for example, development vs production)
* Gradually migrate between keys during rotation

### Key aliases

Each API key can be assigned an alias to identify it. When you add a key, you can specify a custom alias, or the system will use `default` as the alias.

When making requests, AI Gateway uses the key with the `default` alias by default. To use a different key, include the `cf-aig-byok-alias` header with the alias of the key you want to use.

### Example: Using a specific key alias

If you have multiple OpenAI keys configured with different aliases (for example, `default`, `production`, and `testing`), you can specify which one to use:

Terminal window

```

# Uses the key with alias "default" (no header needed)

curl https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/openai/chat/completions \

  -H 'cf-aig-authorization: Bearer {CF_AIG_TOKEN}' \

  -H "Content-Type: application/json" \

  -d '{"model": "gpt-4", "messages": [...]}'


```

Terminal window

```

# Uses the key with alias "production"

curl https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/openai/chat/completions \

  -H 'cf-aig-authorization: Bearer {CF_AIG_TOKEN}' \

  -H 'cf-aig-byok-alias: production' \

  -H "Content-Type: application/json" \

  -d '{"model": "gpt-4", "messages": [...]}'


```

Terminal window

```

# Uses the key with alias "testing"

curl https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/openai/chat/completions \

  -H 'cf-aig-authorization: Bearer {CF_AIG_TOKEN}' \

  -H 'cf-aig-byok-alias: testing' \

  -H "Content-Type: application/json" \

  -d '{"model": "gpt-4", "messages": [...]}'


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ai-gateway/","name":"AI Gateway"}},{"@type":"ListItem","position":3,"item":{"@id":"/ai-gateway/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/ai-gateway/configuration/bring-your-own-keys/","name":"BYOK (Store Keys)"}}]}
```

---

---
title: Workers integration
description: Cloudflare Secrets Store is a secure, centralized location in which account-level secrets are stored and managed. The secrets are securely encrypted and stored across all Cloudflare data centers.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/secrets-store/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Workers integration

[Cloudflare Secrets Store](https://developers.cloudflare.com/secrets-store/) is a secure, centralized location in which account-level secrets are stored and managed. The secrets are securely encrypted and stored across all Cloudflare data centers.

Consider the steps below to learn how to use values from your account secrets store with [Cloudflare Workers](https://developers.cloudflare.com/workers/).

Note

This is different from Workers [Variables and Secrets](https://developers.cloudflare.com/workers/configuration/secrets/), where you define and manage your secrets on a per-Worker level.

## Before you begin

* If [using the Dashboard](#via-dashboard), make sure you already have a Workers application. Refer to the [Workers get started](https://developers.cloudflare.com/workers/get-started/dashboard/) for guidance.
* You should also have a store created under the **Secrets Store** tab on the Dashboard. The first store in your account is created automatically when a user with [Super Administrator or Secrets Store Admin role](https://developers.cloudflare.com/secrets-store/access-control/) interacts with it.  
   * If no store exists in your account yet and you have the necessary permissions, you can use the [Wrangler command](https://developers.cloudflare.com/workers/wrangler/commands/secrets-store/#secrets-store-store) `secrets-store store create <name> --remote` to create your first store.

Local development mode

This guide assumes you are working in production. To use Secrets Store locally, you must use `secrets-store secret` [Wrangler commands](https://developers.cloudflare.com/workers/wrangler/commands/) without the `--remote` flag.

## 1\. Set up account secrets in Secrets Store

Follow the steps below to create secrets. You must have a [Super Administrator or a Secrets Store Admin role](https://developers.cloudflare.com/secrets-store/access-control/) within your Cloudflare account.

Note

You may also add account secrets directly from the Workers settings on the dashboard. You can skip to [step 2](#via-dashboard) to do that.

* [ Wrangler ](#tab-panel-10378)
* [ Dashboard ](#tab-panel-10379)
* [ API ](#tab-panel-10380)

Use the [Wrangler command](https://developers.cloudflare.com/workers/wrangler/commands/secrets-store/#secrets-store-secret) `secrets-store secret create`.

To use the following example, replace the store ID and secret name by your actual data. You can find and copy the store ID from the [Secrets Store tab ↗](https://dash.cloudflare.com/?to=/:account/secrets-store/) on the dashboard or use `wrangler secrets-store store list`.

Note that a secret name cannot contain spaces.

Terminal window

```

npx wrangler secrets-store secret create <STORE_ID> --name MY_SECRET_NAME --scopes workers --remote


```

```

✓ Enter a secret value: › ***


🔐 Creating secret... (Name: MY_SECRET_NAME, Value: REDACTED, Scopes: workers, Comment: undefined)

✓ Select an account: › My account

✅ Created secret! (ID: 13bc7498c6374a4e9d13be091c3c65f1)


```

1. In the Cloudflare dashboard, go to the **Secrets Store** page.  
[ Go to **Secrets Store** ](https://dash.cloudflare.com/?to=/:account/secrets-store)
2. Select **Create secret**.
3. Fill in the required fields, choosing _Workers_ as the **Permission scope**. Once the secret is saved, the secret value will no longer be available for viewing.
4. (Optional) Select **Add additional secret** to create more than one secret at a time.
5. Select **Save** to confirm.

You can find and copy the store ID from the [Secrets Store tab ↗](https://dash.cloudflare.com/?to=/:account/secrets-store/) on the dashboard or use the [Wrangler command](https://developers.cloudflare.com/workers/wrangler/commands/secrets-store/#secrets-store-store). Also, make sure your secret `name` does not contain spaces.

Refer to [Secrets Store API](https://developers.cloudflare.com/api/resources/secrets%5Fstore/) for the full API documentation.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Secrets Store Write`

Create a secret

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/secrets_store/stores/$STORE_ID/secrets" \

  --request POST \

  --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \

  --header "X-Auth-Key: $CLOUDFLARE_API_KEY" \

  --json '[

    {

        "name": "<MY_SECRET_NAME>",

        "value": "<SECRET_VALUE>",

        "scopes": [

            "workers"

        ],

        "comment": ""

    },

    {

        "name": "<MY_SECRET_NAME_2>",

        "value": "<SECRET_VALUE>",

        "scopes": [

            "workers"

        ],

        "comment": ""

    }

  ]'


```

Refer to [manage account secrets](https://developers.cloudflare.com/secrets-store/manage-secrets/) for further options.

## 2\. Bind an account secret to your Worker

[Bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/) allow your Worker to interact with resources on your Cloudflare account.

To bind an account secret to your Worker, you must have one of the following [roles within your Cloudflare account](https://developers.cloudflare.com/secrets-store/access-control/):

* Super Administrator
* Secrets Store Deployer

### Via Wrangler

1. Add a Secrets Store binding to your [Wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/):  
   * `binding`: a descriptive name for your binding. This will be used in the Workers application when [accessing your secret on the env object](https://developers.cloudflare.com/secrets-store/integrations/workers/#3-access-the-secret-on-the-env-object).  
   * `store_id`: the corresponding Secrets Store ID where your account secret was created.  
   * `secret_name`: the unique secret name, defined when your account secret was created.

* [  wrangler.jsonc ](#tab-panel-10376)
* [  wrangler.toml ](#tab-panel-10377)

JSONC

```

{

  "main": "./src/index.js",

  "secrets_store_secrets": [

    {

      "binding": "<BINDING_VARIABLE>",

      "store_id": "<STORE_ID>",

      "secret_name": "<MY_SECRET_NAME>"

    }

  ]

}


```

TOML

```

main = "./src/index.js"


[[secrets_store_secrets]]

binding = "<BINDING_VARIABLE>"

store_id = "<STORE_ID>"

secret_name = "<MY_SECRET_NAME>"


```

### Via Dashboard

1. In the Cloudflare dashboard, go to **Workers & Pages**.  
[ Go to **Workers & Pages** ](https://dash.cloudflare.com/?to=/:account/workers-and-pages)
2. Select a Workers application.
3. Go to **Settings** \> **Bindings** and select **Add**.
4. On the **Add a resource binding** side panel, choose **Secrets Store**.
5. Fill in the required fields:  
   * **Variable name**: a name for the binding. This will be used for your Worker to access the secret ([step 3](#3-access-the-secret-on-the-env-object) below).  
   * **Secret name**: select from the list of available account secrets created in [step 1](#1-set-up-account-secrets-in-secrets-store).  
   * (Optional - Admins only) If the secret you need does not exist yet, select **Create secret**. This will add an account level secret in the same way as if you had [created it on the Secrets Store](https://developers.cloudflare.com/secrets-store/manage-secrets/).
6. Select **Deploy** to deploy your binding. When deploying, there are two options:  
   * **Deploy:** Immediately deploy the binding to 100% of your audience.  
   * **Save version:** Save a version of the binding which you can deploy in the future.

## 3\. Access the secret on the `env` object

[Bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/) are located on the `env` object. To access the secret you first need an asynchronous call.

### Call `get()` on the binding variable

Local development mode

You cannot access production secrets (created on the dashboard, via API, or with the `--remote` flag) from your local development setup. To use Secrets Store locally, you must use `secrets-store secret` [Wrangler commands](https://developers.cloudflare.com/workers/wrangler/commands/) without the `--remote` flag.

JavaScript

```

export default {

  async fetch(request, env) {

    // Example of using the secret safely in an API request

    const APIkey = await env.<BINDING_VARIABLE>.get()


    const response = await fetch("https://api.example.com/data", {

      headers: { "Authorization": `Bearer ${APIKey}` },

    });


    if (!response.ok) {

      return new Response("Failed to fetch data", { status: response.status });

    }


    const data = await response.json();

    return new Response(JSON.stringify(data), {

      headers: { "Content-Type": "application/json" },

    });

  },

};


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/secrets-store/","name":"Secrets Store"}},{"@type":"ListItem","position":3,"item":{"@id":"/secrets-store/integrations/","name":"Secrets Store integrations"}},{"@type":"ListItem","position":4,"item":{"@id":"/secrets-store/integrations/workers/","name":"Workers integration"}}]}
```

---

---
title: Cloudflare Security Center
description: Review security insights, investigate threats, and protect your brand from impersonation.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Cloudflare Security Center

Cloudflare Security Center brings together your Cloudflare security products, threat intelligence from Cloudflare's global network, and configuration analysis into a unified security intelligence solution. Security Center enables you to strengthen your security posture by:

* **Mapping your attack surface** — identifying the Internet-facing assets (domains, DNS records, and IP addresses) associated with your Cloudflare account
* **Providing asset inventory and discovery** — listing the infrastructure Cloudflare detects across your account so you can review what is exposed
* **Identifying potential security risks, misconfigurations, and vulnerabilities** — running automated scans that compare your current Cloudflare configuration against ideal settings
* **Helping you mitigate these risks** — connecting each finding to the relevant Cloudflare product setting so you can resolve issues from the dashboard

## Main features

* **[Security Insights](https://developers.cloudflare.com/security/security-insights/)**: Review and manage potential security risks and vulnerabilities associated with your IT infrastructure. Security Insights scans your Cloudflare account settings — including DNS records, SSL/TLS certificates, WAF configurations, and Access configurations — and reports findings with severity levels.
* **[Infrastructure](https://developers.cloudflare.com/security-center/infrastructure/)**: Review and manage your IT infrastructure. The Infrastructure tab displays the domains, IP addresses, and other assets associated with your Cloudflare account.
* **[Investigate](https://developers.cloudflare.com/security-center/investigate/)**: Investigate threats using data from Cloudflare's global network. Look up any IP address, domain, or hostname to view its category, country of origin, and passive DNS records.
* **[Security Reports](https://developers.cloudflare.com/analytics/account-and-zone-analytics/app-security-reports/)** (beta): Gain visibility into requests blocked or challenged by Cloudflare application security products, including [HTTP DDoS Protection](https://developers.cloudflare.com/ddos-protection/managed-rulesets/http/), [WAF](https://developers.cloudflare.com/waf/), and [Bot Management](https://developers.cloudflare.com/bots/).
* **[Brand Protection](https://developers.cloudflare.com/security-center/brand-protection/)** (beta): Search for newly registered domains that may be attempting to impersonate your brand. Brand Protection monitors for typosquatting, homoglyph attacks, and service concatenation.
[ Get started ](https://developers.cloudflare.com/security-center/get-started/) 

---

## Availability

Cloudflare Security Center is available to customers on all plans.

The frequency of automatic security scans depends on your Cloudflare plan, ranging from every 7 days on Free, Pro, and Business plans to every 3 days on Enterprise plans. Refer to [Scan frequency](https://developers.cloudflare.com/security/security-insights/how-it-works/#scan-frequency) for more information.

If you have any comments, questions, or bugs to report, create a post in the [Cloudflare Community forum ↗](https://community.cloudflare.com/c/security/security-center/65).

## Limitations

* Users with an [Administrator Read Only](https://developers.cloudflare.com/fundamentals/manage-members/roles/#account-scoped-roles) role cannot access the Cloudflare Security Center.
* Only Cloudflare accounts with at least one Business or Enterprise zone (domain on your account), or accounts on the Teams Standard or Teams Enterprise plans, can manually start a new scan.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}}]}
```

---

---
title: Get started
description: Use Security Insights to scan your account for misconfigurations and vulnerabilities.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Get started

Security Center scans your Cloudflare account configuration and identifies potential security risks, misconfigurations, and vulnerabilities across your domains. This guide covers the initial setup.

## Prerequisites

* A Cloudflare account.
* At least one [zone](https://developers.cloudflare.com/fundamentals/concepts/accounts-and-zones/#zones) (domain or subdomain) added to your Cloudflare account.

## Turn Security Insights on or off

Security Insights scans are enabled by default. Security Insights will scan your Cloudflare environment and provide you with a list of detected [insights](https://developers.cloudflare.com/security/security-insights/). Refer to [How it works](https://developers.cloudflare.com/security/security-insights/how-it-works/) to learn more about how Security Insights perform a scan.

The initial scan time depends on the number of IT assets in all the domains of your Cloudflare account. When the scan is complete, the status of the page will change from **Scan in Progress** to **Last scan performed on: `<DATE_TIME>`**.

You can decide to stop a scan, and restart a scan later.

To disable scans:

1. In the Cloudflare dashboard, go to the **Security Insights** page.  
[ Go to **Security insights** ](https://dash.cloudflare.com/?to=/:account/security-center)
2. Go to **Disable Security Center scans**, select **Disable scans**.

To restart a scan:

1. In the Cloudflare dashboard, go to the **Security Insights** page.  
[ Go to **Security insights** ](https://dash.cloudflare.com/?to=/:account/security-center)
2. Select **Scan now**.

### Start a new scan

To manually start a scan:

1. In the Cloudflare dashboard, go to the **Security insights** page.  
[ Go to **Security insights** ](https://dash.cloudflare.com/?to=/:account/security-center)
2. Select **Scan now**.

Note

Only accounts with at least one Business or Enterprise zone, or accounts on the Teams Standard or Teams Enterprise plan, can start manual scans. All plans receive automatic scans.

### Scan frequency

Cloudflare performs scans automatically for all accounts and zones by default. On-demand scans are available on all plans:

| Plan             | Scan Frequency | On-Demand |
| ---------------- | -------------- | --------- |
| Free             | Every 7 days   | Yes       |
| Pro and Business | Every 3 days   | Yes       |
| Enterprise       | Daily          | Yes       |

For more details, refer to [How it works](https://developers.cloudflare.com/security/security-insights/how-it-works/#scan-frequency).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}},{"@type":"ListItem","position":3,"item":{"@id":"/security-center/get-started/","name":"Get started"}}]}
```

---

---
title: Threat Intelligence APIs
description: Query Cloudflare threat intelligence data for IPs, domains, ASNs, and more.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Threat Intelligence APIs

Cloudflare provides a series of endpoints covering various areas of internet security and insights. Based on your Cloudflare plan type, the [limit](https://developers.cloudflare.com/security-center/intel-apis/limits/) of API calls will vary per month.

| Intelligence Endpoint                                                                                                                                              | Definition                                                                                                                                                       |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [ASN Intelligence](https://developers.cloudflare.com/api/resources/intel/subresources/asn/methods/get/)                                                            | Provides an overview of the Autonomous System Number (ASN) and a list of subnets for it.                                                                         |
| [Custom Indicator Feed Download](https://developers.cloudflare.com/api/resources/intel/subresources/indicator%5Ffeeds/subresources/downloads/)                     | Provides the ability to download any custom indicator feeds that users create.                                                                                   |
| [Domain Intelligence](https://developers.cloudflare.com/api/resources/intel/subresources/domains/methods/get/)                                                     | Provides security details and statistics about a domain.                                                                                                         |
| [Domain History](https://developers.cloudflare.com/api/resources/intel/subresources/domain%5Fhistory/methods/get/)                                                 | Provides historical security threat and content categories that are currently and previously assigned to a domain.                                               |
| [IP Intelligence](https://developers.cloudflare.com/api/resources/intel/subresources/ips/methods/get/)                                                             | Provides the geolocation, ASN, infrastructure type of the ASN, and any security threat categories of an IP address.                                              |
| [Passive DNS by IP](https://developers.cloudflare.com/api/resources/intel/subresources/dns/methods/list/)                                                          | Provides a list of all the domains, including first seen and last seen dates, that have resolved to a specific IP address.                                       |
| [Phishing Intelligence](https://developers.cloudflare.com/api/resources/brand%5Fprotection/methods/url%5Finfo/)                                                    | Provides phishing details about a URL.                                                                                                                           |
| [Miscategorization Intelligence](https://developers.cloudflare.com/api/resources/intel/subresources/miscategorizations/methods/create/)                            | Enables users to submit requests for modifying a domain's category, subsequently undergoing review by the Cloudflare Intelligence team.                          |
| [Priority Intelligence Requirements](https://developers.cloudflare.com/api/resources/cloudforce%5Fone/subresources/requests/subresources/priority/methods/create/) | Provides a structured approach to identifying intelligence gaps, formulating precise requirements, and organizing them into categories.                          |
| [Request for Information](https://developers.cloudflare.com/api/resources/cloudforce%5Fone/subresources/requests/methods/create/)                                  | Creates a targeted inquiry for specific intelligence insights to help organizations understand and respond to imminent security threats and vulnerabilities.     |
| [Threat Events](https://developers.cloudflare.com/api/resources/cloudforce%5Fone/subresources/scans/subresources/results/methods/get/)                             | Allows customers to look into the Cloudflare telemetry and threat actor activity on the Cloudflare network.                                                      |
| [WHOIS](https://developers.cloudflare.com/api/resources/intel/subresources/whois/methods/get/)                                                                     | Provides the WHOIS registration information for a specific domain.                                                                                               |
| [DDoS Botnet Threat Feed](https://developers.cloudflare.com/ddos-protection/botnet-threat-feed/)(early access)                                                     | Provides information to service providers about their own IP addresses that have participated in HTTP DDoS attacks as observed from Cloudflare's global network. |
| [Cloudforce One](https://developers.cloudflare.com/api/resources/cloudforce%5Fone/subresources/requests/subresources/assets/methods/create/)                       | Enable users to list, delete, get, or update a request asset.                                                                                                    |
| [Brand Protection API](https://developers.cloudflare.com/api/resources/brand%5Fprotection/)                                                                        | Provides the ability to create and delete queries, download matches for logo and string queries, read matches for logo and string queries.                       |

## API Examples

Below you can find examples of Threat Intelligence API calls. Make sure you are using an [API Token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) with the appropriate edit permissions. For comprehensive details, navigate to the respective API documentation using the links above.

### ASN Intelligence

Get ASN Overview

Terminal window

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/intel/asn/13335" \

--header "Authorization: Bearer <API_TOKEN>" | jq .


# Example response:

{

    "result": {

        "asn": 13335,

        "description": "CLOUDFLARENET",

        "country": "US",

        "type": "isp"

    },

    "success": true,

    "errors": [],

    "messages": []

}


```

### Custom Indicator Feed Download

Download Custom Indicator Feed

Terminal window

```

curl "https://api.cloudflare.com/client/v4/accounts/10d79d097895ae7ed7942a2b3832186c/intel/indicator-feeds/31/download" \

--header "Authorization: Bearer <API_TOKEN>" | jq .


# Example response:

{

    "result": [

        {

            "type": "bundle",

            "id": "bundle--f4a735b7-b330-465d-8e6e-87b3c6a01287",

            "objects":

                [

                    {

                        "type": "indicator",

                        "spec_version": "2.1",

                        "id": "indicator--3d0ad6e0-3d49-4575-a0cb-d0e5c8b81f08",

                        "created": "2024-07-18T00:00:00Z",

                        "modified": "2024-07-18T00:00:00Z",

                        "name": "Malicious domain ahilesopolker.com",

                        "description": "This domain is associated with malicious activity.",

                        "pattern": "[domain-name:value = 'ahilesopolker.com']",

                        "pattern_type": "stix",

                        "valid_from": "2024-07-18T00:00:00Z"

                    },

                    {

                        "type": "domain-name",

                        "spec_version": "2.1",

                        "id": "domain-name--b252f8d7-5b63-4b59-9d58-8f313db76c35",

                        "value": "ahilesopolker.com",

                        "object_marking_refs": [ "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da" ],

                        "created": "2024-07-18T00:00:00Z",

                        "modified": "2024-07-18T00:00:00Z"

                        }

],

    },

    "success": true,

    "errors": [],

    "messages": []

}


```

### Domain Intelligence

Get Domain Details

Terminal window

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/intel/domain?domain=cloudflare.com" \

--header "Authorization: Bearer <API_TOKEN>" | jq .


# Example response:

{

    "result": {

        "domain": "cloudflare.com",

        "resolves_to_refs": [

            {

                "id": "ipv4-addr--71f6bb54-e0c5-5e7d-b939-5698fc15a102",

                "value": "104.16.133.229"

            },

            {

                "id": "ipv4-addr--015b0df4-7fcd-5409-9b56-cfd300c662f6",

                "value": "104.16.132.229"

            },

            {

                "id": "ipv6-addr--4a7455cd-e8d0-5bfb-8bdb-f6ebb1759508",

                "value": "2606:4700::6810:85e5"

            },

            {

                "id": "ipv6-addr--68f89579-7204-5ebd-a851-e91b3a86fc6d",

                "value": "2606:4700::6810:84e5"

            }

        ],

        "application": {},

        "content_categories": [

            {

                "id": 155,

                "super_category_id": 26,

                "name": "Technology"

            },

            {

                "id": 26,

                "name": "Technology"

            }

        ],

        "additional_information": {},

        "type": "Apex domain",

        "notes": "Apex domain given."

    },

    "success": true,

    "errors": [],

    "messages": []

}


```

### Domain History

Get Domain History

Terminal window

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/intel/domain-history?domain=cloudflare.com" \

--header "Authorization: Bearer <API_TOKEN>" | jq .


{

    "result": [

        {

            "domain": "cloudflare.com",

            "categorizations": [

                {

                    "categories": [

                        {

                            "id": 155,

                            "name": "Technology"

                        }

                    ],

                    "start": "2020-12-16T19:49:30.533482Z",

                    "end": "2023-05-31T08:12:53.547029Z"

                },

                {

                    "categories": [

                        {

                            "id": 115,

                            "name": "Login Screens"

                        },

                        {

                            "id": 155,

                            "name": "Technology"

                        }

                    ],

                    "start": "2023-05-31T08:12:53.547029Z"

                }

            ]

        }

    ],

    "success": true,

    "errors": [],

    "messages": []

}


```

### IP Intelligence

Get IP Overview

Terminal window

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/intel/ip?ipv4=1.1.1.1" \

--header "Authorization: Bearer <API_TOKEN>" | jq .


# Example response:

{

    "result": [

        {

            "ip": "1.1.1.1",

            "belongs_to_ref": {

                "id": "autonomous-system--2fa28d71-3549-5a38-af05-770b79ad6ea8",

                "value": 13335,

                "type": "isp",

                "country": "US",

                "description": "CLOUDFLARENET"

            },

            "ip_lists": null,

            "ptr_lookup": {

                "ptr_domains": [

                    "one.one.one.one."

                ],

                "ptr_lookup_errors": ""

            },

            "iana_reservations": []

        }

    ],

    "success": true,

    "errors": [],

    "messages": []

}


```

### Passive DNS by IP

Get Passive DNS by IP

Terminal window

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/intel/dns?ipv4=1.1.1.1&start=2023-07-15&end=2023-07-18&per_page=5" \

--header "Authorization: Bearer <API_TOKEN>" | jq .


# Example response:

{

    "result": {

        "reverse_records": [

            {

                "first_seen": "2023-07-15T00:00:00Z",

                "last_seen": "2023-07-18T00:00:00Z",

                "hostname": "internet-ping.svc.starlink.com"

            },

            {

                "first_seen": "2023-07-15T00:00:00Z",

                "last_seen": "2023-07-18T00:00:00Z",

                "hostname": "one.one.one.one"

            },

            {

                "first_seen": "2023-07-15T00:00:00Z",

                "last_seen": "2023-07-18T00:00:00Z",

                "hostname": "ping.ui.com"

            },

            {

                "first_seen": "2023-07-15T00:00:00Z",

                "last_seen": "2023-07-18T00:00:00Z",

                "hostname": "ping.ubnt.com"

            },

            {

                "first_seen": "2023-07-15T00:00:00Z",

                "last_seen": "2023-07-18T00:00:00Z",

                "hostname": "bflow.tiki.video"

            }

        ],

        "count": 778,

        "page": 1,

        "per_page": 5

    },

    "success": true,

    "errors": [],

    "messages": []

}


```

### Phishing Intelligence

Get results for a URL scan

Terminal window

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/brand-protection/url-info?url=http://worcester-realistic-ellen-portland.trycloudflare.com/login.html" \

--header "Authorization: Bearer <API_TOKEN>" | jq .


# Example response:

{

    "errors": [],

    "messages": [],

    "result": [

        {

            "categorizations": [],

            "model_results": [

                {

                    "model_name": "MACHINE_LEARNING_v2",

                    "model_score": 0.999

                }

            ],

            "rule_matches": [

                {

                    "description": "Match frequently used phishing kit (Discord, Facebook, Instagram, Twitter)",

                    "name": "phishkit.social"

                }

            ],

            "scan_status": {

                "last_processed": "Wed, 19 Jul 2023 14:15:28 GMT",

                "scan_complete": true,

                "status_code": 200,

                "submission_id": 23098147

            },

            "url": "http://worcester-realistic-ellen-portland.trycloudflare.com/login.html"

        }

    ],

    "success": true

}


```

### Miscategorization Intelligence

Create Miscategorization

Terminal window

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/intel/miscategorization" \

--header "Authorization: Bearer <API_TOKEN>" \

--header "Content-Type: application/json" \

--data '{

    "content_adds": [

        82

    ],

    "content_removes": [

        82

    ],

    "indicator_type": "url",

    "ip": null,

    "security_adds": [

        117,

        131

    ],

    "security_removes": [

        117

    ],

    "url": "https://wrong-category.example.com"

}'


# Example response:

{

    "result": "",

    "success": true,

    "errors": [],

    "messages": []

}


```

### WHOIS

Get WHOIS Record

Terminal window

```

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/intel/whois?domain=cloudflare.com" \

--header "Authorization: Bearer <API_TOKEN>" | jq .


# Example response:

{

    "result": {

        "domain": "cloudflare.com",

        "created_date": "2009-02-17",

        "updated_date": "2017-05-24",

        "registrant": "DATA REDACTED",

        "registrant_org": "DATA REDACTED",

        "registrant_country": "United States",

        "registrant_email": "https://domaincontact.cloudflareregistrar.com/cloudflare.com",

        "registrar": "CloudFlare, Inc.",

        "nameservers": [

            "ns3.cloudflare.com",

            "ns4.cloudflare.com",

            "ns5.cloudflare.com",

            "ns6.cloudflare.com",

            "ns7.cloudflare.com"

        ]

    },

    "success": true,

    "errors": [],

    "messages": []

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}},{"@type":"ListItem","position":3,"item":{"@id":"/security-center/intel-apis/","name":"Threat Intelligence APIs"}}]}
```

---

---
title: Limits
description: Limits
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Limits

## API request limits

All API calls made to Threat Intelligence endpoints will contribute to the monthly quota. Additionally, utilizing features within the Security Center such as Investigate and Brand Protection, or other products, such as client-side security, which also leverage the Security Intelligence APIs, will also contribute to the consumption of the quota.

These request limits currently do not apply to the DDoS Botnet Threat Feed API.

| Cloudflare Plan        | Calls per month |
| ---------------------- | --------------- |
| Free                   | 100             |
| Pro                    | 100             |
| Business               | 100             |
| Enterprise             | 2,500           |
| Cloudforce One Core    | 10,000          |
| Cloudforce One Premier | 50,000          |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}},{"@type":"ListItem","position":3,"item":{"@id":"/security-center/intel-apis/","name":"Threat Intelligence APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/security-center/intel-apis/limits/","name":"Limits"}}]}
```

---

---
title: Manage miscategorization reports
description: Submit domain miscategorization reports using the Cloudflare API.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Manage miscategorization reports

This guide will show you how to manage miscategorization of reports. To complete this guide, you will need to generate an [API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/).

1. Create an [API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) if you do not have one already.
2. Choose **Custom Token**.
3. Name the token, and grant permissions.
4. Send a `POST` request to the miscategorization [API endpoint ↗](https://developers.cloudflare.com/api/resources/intel/subresources/miscategorizations/methods/create/). You can find an example below:

Example of a POST request to miscategorization API

```

export URL="https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/intel/miscategorization"

curl -X POST "$URL" \

     -H "Authorization: Bearer $TOKEN" \

     -H "Content-Type:application/json" \

--data '{

  "content_adds": [

  ],

  "content_removes": [

  ],

  "indicator_type": "domain",

  "ip": null,

  "security_adds": [

    115

  ],

  "security_removes": [

  ],

  "url": "cloudflare.com"

}'


```

You should receive a response with the value `"success": true`:

```

{

  "result": "",

  "success": true,

  "errors": [],

  "messages": []

}


```

Once you send the request, the Cloudflare Support team will receive it and will be able to take action.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}},{"@type":"ListItem","position":3,"item":{"@id":"/security-center/intel-apis/","name":"Threat Intelligence APIs"}},{"@type":"ListItem","position":4,"item":{"@id":"/security-center/intel-apis/manage-miscategorization-reports/","name":"Manage miscategorization reports"}}]}
```

---

---
title: Cloudforce One
description: Access Cloudflare threat intelligence, reports, and automated security rules.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Cloudforce One

Note

You must have a Cloudforce One subscription to access Cloudforce One on the dashboard.

Cloudforce One is Cloudflare's Threat Intelligence Platform (TIP). It collects and correlates threat data from Cloudflare telemetry, then surfaces that data as visualizations, automated rules, and analyst-reviewed intelligence.

Security Operations Center ([SOC ↗](https://www.cloudflare.com/en-gb/learning/security/glossary/what-is-a-security-operations-center-soc/)) teams use Cloudforce One to investigate threats, track adversaries, and take action — such as pushing firewall rules or exporting indicators.

## Access Cloudforce One

Note

You must have a **Cloudforce One subscription** to access the platform.

To access Cloudforce One:

1. In the Cloudflare dashboard, go to the **Threat intelligence** page.  
[ Go to **Threat intelligence** ](https://dash.cloudflare.com/?to=/:account/security-center/threat-intelligence)

You can also use Cloudforce One via the [REST API](https://developers.cloudflare.com/api/resources/cloudforce%5Fone/subresources/requests/subresources/assets/).

The Threat Intelligence page contains four sections:

* **Threat Events** — View and analyze threat intelligence data collected across the Cloudflare network.
* **Priority Intelligence Requirements (PIRs)** — Define the intelligence topics your organization needs to track. PIRs help you identify gaps in your threat coverage.
* **Requests for Information (RFIs)** — Submit specific queries to the Cloudforce One analysis team.
* **Reports** — Read the latest threat reports published by Cloudforce One.

## Analyze threat events

Threat events represent Cloudflare telemetry and threat actor activity observed on the Cloudflare network. Use threat events to investigate threats targeting your organization or your industry.

To access threat events, go to the **Threat intelligence** page in the Cloudflare dashboard.

[ Go to **Threat intelligence** ](https://dash.cloudflare.com/?to=/:account/security-center/threat-intelligence) 

You can also access threat events via the [API](https://developers.cloudflare.com/api/resources/cloudforce%5Fone/subresources/threat%5Fevents/).

Cloudforce One customers have access to the following datasets:

* Advanced Persistent Threats (APTs) — the default dataset
* [DDoS ↗](https://www.cloudflare.com/learning/ddos/what-is-a-ddos-attack/) attacks
* Cybercrime
* Compromised devices
* Residential proxies
* [WAF](https://developers.cloudflare.com/waf/) attacks

### Identify the adversary

The Cloudflare dashboard provides visualizations that include:

* **Sankey diagrams** — Flow diagrams that visualize the distribution of attacks across origins and targets. Use these to trace attack flows from origin infrastructure to targets.
* **Industry distribution** — Identify whether campaigns are targeting your specific sector (for example, finance or retail).

### Search for indicators

Search across global datasets for specific indicators, including:

* IP addresses and domains
* File hashes
* [JA3 fingerprints](https://developers.cloudflare.com/bots/additional-configurations/ja3-ja4-fingerprint/) — TLS client fingerprints used to profile specific SSL/TLS clients across different destinations
* Threat insights — Link events to specific campaigns or threat actor names (for example, APT28).

### Create WAF Rules and receive notifications

* **Saved views** — Save custom filters for recurring threat event investigations.
* **Automated rules** — Generate security rules from threat data and push them to your Cloudflare [WAF](https://developers.cloudflare.com/waf/) or firewall.
* **[STIX2 ↗](https://www.cloudflare.com/en-gb/learning/security/what-is-stix-and-taxii/) exports** — Export threat intelligence in STIX2 format for integration with third-party [SIEM ↗](https://www.cloudflare.com/en-gb/learning/security/what-is-siem/) (Security Information and Event Management) or SOAR (Security Orchestration, Automation, and Response) platforms.

## Use Cloudy to analyze threat events

You can use Cloudy, Cloudflare's AI Agent, to receive an analysis and summary of threat events.

To analyze threat events using Cloudy:

1. In the Cloudflare dashboard, go to the **Threat intelligence** page.  
[ Go to **Threat intelligence** ](https://dash.cloudflare.com/?to=/:account/security-center/threat-intelligence)
2. Go to **Threat Events** \> **Analyze with Cloudy**.

Cloudy will show you the top threat events, analyze them, and give you a summary of threat events. You can also decide to receive an analysis based on **Attacker**, **Indicator**, and more. For example, you can enter "Give me a summary of threat events for ABC Attacker". Cloudy will then summarize threat events for ABC attacker.

## Submit RFIs

To submit RFIs (Request for Information):

1. In the Cloudflare dashboard, go to the **Threat Intelligence** page.  
[ Go to **Threat intelligence** ](https://dash.cloudflare.com/?to=/:account/security-center/threat-intelligence)
2. Select **Requests for Information**.
3. Select **New Request**.
4. Fill in the required fields, then select **Save**.

List of RFI types

The following request types are available when you submit a Request for Information:

* **Binary Analysis - IOCs**: Conduct high-level malware analysis to produce [indicators of compromise (IOCs) ↗](https://www.cloudflare.com/en-gb/learning/security/what-are-indicators-of-compromise/) such as a callback domain (a domain the malware communicates with) or IP address.
* **Binary Analysis - Report**: A detailed analysis of a malware sample. The report includes an attribution assessment (identifying the likely threat actor) and extracts the configuration of the sample for further analysis. Use this type when you are investigating an incident or developing detection logic in an Endpoint Detection and Response ([EDR ↗](https://en.wikipedia.org/wiki/Endpoint%5Fdetection%5Fand%5Fresponse)) tool or network sensor.
* **DDoS Attack**: Confirm whether a [DDoS attack ↗](https://www.cloudflare.com/learning/ddos/what-is-a-ddos-attack/) is occurring against a specific website. The response includes any available indicators and potential attribution.
* **Indicator Analysis - IOCs**: Conduct DNS lookups, origin pivots, and account pivots to provide indicators such as DNS resolutions, origin IPs, and subdomains. Analysis can include account registration patterns and victimology (identifying who was targeted).
* **Indicator Analysis - Report**: A detailed analysis of indicators written in a formal, structured format. In addition to listing [IOCs ↗](https://www.cloudflare.com/en-gb/learning/security/what-are-indicators-of-compromise/), the report explains how IOCs function within the attack chain and links them to specific campaigns, threat actors, and their TTPs (Tactics, Techniques, and Procedures).
* **Passive DNS Resolution**: Search the historical pairing of an IP address to the domain it resolved to during a specified time period.
* **Strategic Threat Research**: Analysis of broader, long-term trends across threat actors and industries. This type is supplemented by open-source intelligence and is intended to inform management and planning rather than to produce immediately actionable indicators.
* **Threat Detection Signature - IOCs**: Develop a detection rule — such as a [YARA ↗](https://virustotal.github.io/yara/) rule — that identifies a sample, behavior, or network observable (for example, an IP address, domain, file hash, or HTTP request attribute).
* **Threat Detection Signature - Report**: A detailed analysis that investigates a threat detection alert. Use this type when you need to prioritize your response effort or attribute activity to a threat actor.
* **Traffic Analysis - IOCs**: Review HTTP telemetry for the IOCs in question. The response provides relevant, sanitized traffic that can include the victim country and, in some cases, victim Autonomous System Numbers (ASNs). This also identifies malicious files, payloads, and unusual file paths or request patterns.
* **Traffic Analysis - Report**: Analysis of HTTP telemetry to identify patterns, anomalies, and indicators of malicious behavior. The report provides context for observed network behaviors and maps them to known TTPs of specific threat groups.
* **Vulnerability**: Investigation to attribute vulnerability exploitation to a threat actor, or to identify IPs, domains, or threat actor groups exploiting a specific vulnerability. The response can include relevant, sanitized traffic demonstrating exploitation and identification of victim countries and industries.

Once you select **Save**, the dashboard will display an overview of the shared information consisting of:

* **Status**: When you submit the RFI, the status is `Open`. Once the team accepts the RFI, the status changes to `Accept`. When the team commits to answer your RFI, the status changes to `Complete`.
* **Priority**: Priority of request.
* **Request type**: Choose among a selection of request types, such as DDos Attack, Passive DNS Resolution, and more.
* **Request content**: The content of the request.

The **Responses** section allows you to add clarifying questions and comments.

To view your RFI, select **Cloudforce One Requests** on the sidebar, locate your RFI, then select **View**. From here, you can also choose to edit your existing RFI by selecting **Edit**.

To delete your RFI, the status must be `Open`. Go to the RFI you want to delete, and select **Delete**. On the pop-up, select **Delete** to confirm deletion. Once Cloudflare accepts and begins processing RFIs, you will not be able to delete RFIs.

### Upload and download attachment

You can also choose to upload and download an attachment.

Under **Attachments**, select the file you want to upload, then select **Save**.

To download an attachment, select **Download** on the attachment.

## Improve your security posture or recover from a past incident

Use Cloudforce One to improve your security posture or recover from a past incident.

1. In the [Cloudflare dashboard ↗](https://dash.cloudflare.com), go to **Application security** \> **Incident Response**.
2. **Choose service**: Select one of the services.
3. **Provide request details**:
* Fill in the required information for the service you selected. Select **Next**.
* Review your request, then select **Submit**.
* After you submit your request, the Cloudforce One team will respond.

## Request help for active attack

If you want to stop an active cyber attack, you can request assistance via the Cloudflare dashboard.

1. In the Cloudflare dashboard, go to the **Account home** page and select your account.
[ Go to **Account home** ](https://dash.cloudflare.com/?to=/:account/home) 
1. On the top bar, select **Support** \> **Get help** \> **Under attack**.
2. Under **Request help to stop active cyberattacks**, select **Request help**.
3. The dashboard will show you a pop-up where you will need to enter and confirm your phone number.
4. Once you have entered your phone number, select **Confirm number and request help**. Requesting help from the dashboard will page an incident responder and you can expect a call-back as soon as possible. We advise you to wait for the call-back, and only use the phone-line in case you have not heard back from the team within 10 minutes.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}},{"@type":"ListItem","position":3,"item":{"@id":"/security-center/cloudforce-one/","name":"Cloudforce One"}}]}
```

---

---
title: Open Port Scanning
description: Scan your IP ranges for open ports and receive daily notifications about changes.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Open Port Scanning

Open Port Scanning allows [Magic Transit](https://developers.cloudflare.com/magic-transit/) and [Bring your Own IPs](https://developers.cloudflare.com/byoip/) users to efficiently monitor IP ranges for security vulnerabilities. This API enables users to scan their designated IP ranges, detect any open ports, and receive daily notifications regarding newly opened ports.

You can access this feature via the [API](https://developers.cloudflare.com/api/resources/cloudforce%5Fone/subresources/scans/subresources/config/).

## Prerequisites

* Cloudforce One Administrator, Administrator and Super Administrator roles.
* Account token: **Custom API Token** \> **Cloudforce One:Edit**.

To create a custom API token:

1. From the [Cloudflare dashboard ↗](https://dash.cloudflare.com/profile/api-tokens/), go to **My Profile** \> **API Tokens** for user tokens. Go to **Create Custom Token** \> **Get started**.
2. Enter a **Token name**, for example, `Open Port Scanning`.
3. In **Permissions**:  
   * Choose **Account**.  
   * Select **Cloudforce One** as the account.  
   * Choose **Edit** access.
4. In Client IP Address Filtering:  
   * In **Operator**, select `is in`.  
   * In **Value**, enter a valid IP address.
5. Select **Continue to summary**.
6. Review the token, then select **Create Token**.

Note

The Open Port Scanner will run from a predetermined set of IPs. The Cloudforce One team recommends you to allowlist these IPs in your rules.

## Configure Open Port Scanning

To configure Open Port Scanning, follow these steps:

1. **Create a new scan config**:  
   * **IPs**: Enter the IP ranges you wish to monitor. Ensure that the ranges are correctly formatted to avoid scanning errors. The API will validate if the IPs requested are onboarded to Cloudflare and associated to the account belonging to the API token used.  
   * **Frequency**: Enter the scan frequency in days.  
   * **Ports**: Select the ports to scan. Choose among:  
         * All  
         * Default (refer to [Default ports](https://developers.cloudflare.com/security-center/cloudforce-one/open-port-scanning/#default-ports) for a comprehensive list)  
         * List of specific ports
2. **Scan IPs**: Initiate the scanning process. The system will analyze the specified IP ranges to identify any open ports.
3. **Generate list of open ports**: Once the scan is complete, the API will generate a list of detected open ports for review and action.
4. **Select open ports to list**: Choose which open ports you would like to be notified about. You can exclude any ports that do not require immediate attention.
5. **View differences from previous scan**: The API will highlight any changes in open ports since the last scan, allowing you to quickly assess new vulnerabilities.
6. **Stop scanning**: If necessary, you can stop the scanning process at any time.
7. **Set up alerts**: Configure alerts for specific ports of interest. You will be notified immediately via email or webhook if any of these designated ports become newly open.

Beta feature notice

Open Port Scanning feature is currently in closed beta. The Cloudforce One team appreciates your feedback as the team works to enhance its functionality and user experience. If you want to subscribe to this feature or participate in the beta program, [join our closed beta for Port Scanning ↗](https://www.cloudflare.com/lp/open-port-scanning-beta/).

## Default ports

List of default ports

* `80`
* `631`
* `161`
* `137`
* `123`
* `138`
* `1434`
* `445`
* `135`
* `67`
* `23`
* `53`
* `443`
* `21`
* `139`
* `22`
* `500`
* `68`
* `520`
* `1900`
* `25`
* `4500`
* `514`
* `49152`
* `162`
* `69`
* `5353`
* `111`
* `49154`
* `3389`
* `110`
* `1701`
* `998`
* `996`
* `997`
* `999`
* `3283`
* `49153`
* `445`
* `1812`
* `136`
* `139`
* `143`
* `53`
* `2222`
* `135`
* `3306`
* `2049`
* `32768`
* `5060`
* `8080`
* `1025`
* `1433`
* `3456`
* `80`
* `1723`
* `111`
* `995`
* `993`
* `20031`
* `1026`
* `7`
* `5900`
* `1646`
* `1645`
* `593`
* `1025`
* `518`
* `2048`
* `626`
* `1027`
* `587`
* `177`
* `1719`
* `427`
* `497`
* `8888`
* `4444`
* `1023`
* `65024`
* `199`
* `19`
* `9`
* `49193`
* `1029`
* `1720`
* `49`
* `465`
* `88`
* `1028`
* `17185`
* `1718`
* `49186`
* `548`
* `113`
* `81`
* `6001`
* `2000`
* `10000`
* `31337`

## Frequently Asked Questions

1. What IPs will the scan come from?  
   * `2a09:bac0:1008:5000:1000:0000:0000:0050/104.30.128.13`  
   * `2a09:bac0:1008:5000:1000:0000:0000:0048/104.30.129.33`  
   * `2001:19f0:1000:2941:5400:4ff:fe70:2a7a/140.82.60.241`
2. Can the Port Scanner bypass other security rules configured?  
   * The Cloudforce One team asks customers to ensure they allow the IPs for the scanner to run correctly.
3. How long do scans take?  
   * Depending on the number of IP addresses and number of ports scanned, scans can take between a few minutes and up to 10 hours.
4. Can I stop automatic scanning?  
   * Yes, you can decide at any point to stop scan and restart scans when it is convenient for you.
5. What are the limitations for the scans?  
   * Scans are limited to ranges of up to 5,000 IPs.  
   * The API scans both IPv4 and IPv6 IP addresses.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}},{"@type":"ListItem","position":3,"item":{"@id":"/security-center/cloudforce-one/","name":"Cloudforce One"}},{"@type":"ListItem","position":4,"item":{"@id":"/security-center/cloudforce-one/open-port-scanning/","name":"Open Port Scanning"}}]}
```

---

---
title: Infrastructure
description: View IT assets, domains, and IP addresses associated with your Cloudflare account.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Infrastructure

User permission

Only Super Admin users with edit permissions can start scans, turn scans off, or manage issues.

The **Infrastructure** tab provides an overview of the IT assets associated with your Cloudflare account, including domains, IP addresses, and related configurations.

[Security Insights](https://developers.cloudflare.com/security/security-insights/) scans populate Infrastructure data. Initial scan time depends on the number of IT assets across the domains in your account.

To open the **Infrastructure** tab, go to Account Home > **Security Center** \> **Infrastructure**.

From the Infrastructure tab, you can:

* **Filter the displayed information** — Narrow results by specific assets, domains, or configurations to focus on areas of interest.
* **Print or download a PDF report** — Generate a report of your infrastructure overview for offline review or sharing with your team.
* **Manage your security.txt file** — Create or update a [security.txt](https://developers.cloudflare.com/security-center/infrastructure/security-file/) file that provides security researchers with a standardized way to report vulnerabilities.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}},{"@type":"ListItem","position":3,"item":{"@id":"/security-center/infrastructure/","name":"Infrastructure"}}]}
```

---

---
title: Set up your security.txt file
description: Manage your security.txt file via the dashboard or the API.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Set up your security.txt file

You can manage your [security.txt ↗](https://en.wikipedia.org/wiki/Security.txt) file via the dashboard or the [API](https://developers.cloudflare.com/api/resources/security%5Ftxt/).

Note

When using the API, the preferred languages field name is `preferred_languages` (snake\_case). For example: `"preferred_languages": "en, de"`.

To manage your security.txt file via the Cloudflare dashboard:

* [  New dashboard ](#tab-panel-10389)
* [ Old dashboard ](#tab-panel-10390)

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), select your account and domain.
2. Go to **Security** \> **Settings** and filter by **Web application exploits**.
3. Under **Security.txt** \> **Configurations**, select the edit icon.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/), select your account and domain.
2. Go to **Security** \> **Settings**.
3. Next to **Enable Security.txt**, select **Edit Security.txt**.

From here, you can create and manage your `security.txt` file to provide the security research team with a standardized way to report vulnerabilities.

Fill in the following information:

* **(Required) Contact**: You can enter one of the following to contact you about security issues:  
   * An email address: The email address must start with `mailto:` (for example, `mailto:help@example.com`).  
   * A phone number: The phone number must start with `tel:` (for example, `tel:+1 1234567890`).  
   * A URL link: The URL link must start with `https://` (for example, `https://example.com`).  
Select **Add more** to add multiple contacts.
* **(Required) Expires at**: Enter the expiration date and time of the `security.txt` file.
* **Encryption**: A link to a key which security researchers can use to communicate with you.
* **Acknowledgements**: A link to your acknowledgements page.
* **Canonical**: Links to your `security.txt` file.
* **Hiring**: A link to your security-related job openings.
* **Policy**: A link to a policy describing what security researchers should do when searching for or reporting security issues.
* **Preferred languages**: A list of language codes that your security team speaks.

Once you have entered the necessary information, select **Save**.

To edit your security.txt file:

* Old dashboard: Select **Security** \> **Settings** \> **Edit Security.txt**.
* New security dashboard:  
   1. Go to **Security** \> **Settings** and filter by **Web application exploits**.  
   2. Under **Security.txt** \> **Configurations**, select the edit icon.

To download your security.txt file:

* Old dashboard: Select **Security** \> **Settings** \> **Download Security.txt**.
* New security dashboard:  
   1. Go to **Security** \> **Settings** and filter by **Web application exploits**.  
   2. Under **Security.txt** \> **Configurations**, select the download icon.

To delete your security.txt file:

* Old dashboard:  
   * Select **Security** \> **Settings** \> **Delete Security.txt**.
* New security dashboard:  
   1. Select **Security** \> **Settings** and filter by **Web application exploits**.  
   2. Under **Security.txt** \> **Configurations**, select the edit icon.  
   3. Select **Delete**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}},{"@type":"ListItem","position":3,"item":{"@id":"/security-center/infrastructure/","name":"Infrastructure"}},{"@type":"ListItem","position":4,"item":{"@id":"/security-center/infrastructure/security-file/","name":"Set up your security.txt file"}}]}
```

---

---
title: Investigate
description: Look up threat intelligence for IPs, domains, URLs, and AS numbers.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Investigate

User permission

Investigate is available to all users. Every user can view existing URL scanner reports and initiate new URL scans.

However, advanced intelligence features, including searching for IP and domain intelligence and passive DNS records, are restricted to users with the following roles: Super Admin, Administrator, Brand Protection, Cloudforce One Admin.

Investigate allows you to view a domain’s category, the IP it belongs to, and whether the category has changed before. You can also see which records it points to, including the country of origin and passive DNS records. After searching with Investigate, you will get an API curl to retrieve the same search results.

You can learn more about the IP addresses in your logs by searching via the IP address to view its category and threat data. Enter any IP address, domain name, and hostname to see how it has been categorized from a threat perspective.

Investigate also shows [Web Application Firewall ↗](https://developers.cloudflare.com/waf/) analytics for your websites behind Cloudflare to help you discover what your vulnerabilities are, where attacks come from, and what to do about it.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}},{"@type":"ListItem","position":3,"item":{"@id":"/security-center/investigate/","name":"Investigate"}}]}
```

---

---
title: Change categorization
description: Request domain categorization changes via the dashboard, Radar, or the API.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Change categorization

Cloudflare sorts domains into categories based on their content and security type. You can request categorization changes via the [dashboard](#via-the-cloudflare-dashboard), [Cloudflare Radar](#via-cloudflare-radar), or the [API](#via-the-api).

For a detailed list of categories, refer to [Domain categories](https://developers.cloudflare.com/cloudflare-one/traffic-policies/domain-categories/).

## Via the Cloudflare dashboard

To request a categorization change via the Cloudflare dashboard:

1. In the Cloudflare dashboard, go to the **Investigate** page.  
[ Go to **Investigate** ](https://dash.cloudflare.com/?to=/:account/security-center/investigate)
2. Search for the domain you want to change.
3. In **Domain overview**, select **Request to change categorization**.
4. Choose whether to change a [security category](https://developers.cloudflare.com/cloudflare-one/traffic-policies/domain-categories/#security-categories) or a [content category](https://developers.cloudflare.com/cloudflare-one/traffic-policies/domain-categories/#content-categories).
5. Choose which categories you want to add or remove from the domain.  
Content category limit  
A domain cannot have more than two associated content categories. To propose changes to categories of a domain with more than two existing categories, remove one or more of the existing categories.
6. Select **Submit** to submit your request for review.

Requesting a security category change will trigger a deeper investigation by Cloudflare to confirm that the submission is valid. Requesting a content category change also requires Cloudflare validation, but the turnaround time for these submissions is usually shorter as it requires less investigation.

Your category change requests will be revised by the Cloudflare team depending on the type of change. If your requests have been reviewed and applied by the Cloudflare team, the new categories will be visible in the Cloudflare dashboard in **Security Center** \> **Investigate**, as well as in [Cloudflare Radar ↗](https://radar.cloudflare.com/).

Warning

Cloudflare does not guarantee the category change will be approved.

## Via Cloudflare Radar

To request recategorization via Cloudflare Radar, submit feedback in [Radar Domain Categorization ↗](https://radar.cloudflare.com/domains/feedback).

## Via the API

To request a categorization change via the API:

1. [Create an API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) with permission to edit your Intel account.  
| **Permissions** |       |      |  
| --------------- | ----- | ---- |  
| Account         | Intel | Edit |  
| **Account Resources** |              |  
| --------------------- | ------------ |  
| Include               | All accounts |
2. Make a call to the [miscategorization endpoint](https://developers.cloudflare.com/api/resources/intel/subresources/miscategorizations/methods/create/) including the domain name and any categories you would like to add or remove. For example:  
Terminal window  
```  
curl https://api.cloudflare.com/client/v4/accounts/{account_id}/intel/miscategorization \  
--header "Authorization: Bearer <API_TOKEN>" \  
--header "Content-Type: application/json" \  
--data '{  
  "content_adds": [  
    82  
  ],  
  "content_removes": [  
    155  
  ],  
  "indicator_type": "domain",  
  "ip": null,  
  "security_adds": [  
    117,  
    131  
  ],  
  "security_removes": [  
    83  
  ],  
  "url": "example.com"  
}'  
```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}},{"@type":"ListItem","position":3,"item":{"@id":"/security-center/investigate/","name":"Investigate"}},{"@type":"ListItem","position":4,"item":{"@id":"/security-center/investigate/change-categorization/","name":"Change categorization"}}]}
```

---

---
title: Investigate threats
description: Search for IP, domain, URL, or ASN intelligence in Security Center or Radar.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Investigate threats

Users can investigate the details of an IP address, domain name, URL, or Autonomous System Number (ASN). You can find the Investigate feature in your Cloudflare account's Security Center and in [Cloudflare Radar ↗](https://radar.cloudflare.com/scan).

You can search with Investigate by [IP address](https://developers.cloudflare.com/security-center/investigate/investigate-threats/#ip-address), [domain](https://developers.cloudflare.com/security-center/investigate/investigate-threats/#domain), [URL](https://developers.cloudflare.com/security-center/investigate/investigate-threats/#url) and [AS number](https://developers.cloudflare.com/security-center/investigate/investigate-threats/#as-number).

Note

Search methods are also available through the [API](https://developers.cloudflare.com/security-center/intel-apis/).

## IP Address

An [IP address ↗](https://www.cloudflare.com/learning/dns/glossary/what-is-my-ip-address/) is a unique address that identifies a server. It stands for [Internet Protocol ↗](https://www.cloudflare.com/learning/network-layer/internet-protocol/), which is the set of rules that allows servers to communicate with each other.

IP address search allows you to search both [IPv4 and IPv6 ↗](https://www.cloudflare.com/learning/dns/glossary/what-is-my-ip-address/) addresses and retrieve relevant information such as their pointer records, AS numbers and passive DNS records.

## Domain

A [domain name ↗](https://www.cloudflare.com/learning/dns/glossary/what-is-a-domain-name/) is a string of text that maps to an IP address. Domain names are used to help people remember where websites are hosted. Domain names are purchased through [registrars](https://developers.cloudflare.com/registrar/) and can be acquired easily by anyone.

When you search for a domain name, Cloudflare will provide an overview of the domain's [category](#domain-categories) and IP addresses it currently resolves to.

### Domain categories

For a detailed list of categories, refer to [Domain categories](https://developers.cloudflare.com/cloudflare-one/traffic-policies/domain-categories/).

A domain can have multiple categories. Cloudflare displays both the parent category and the detailed child category. You can [request category changes](https://developers.cloudflare.com/security-center/investigate/change-categorization/) for a domain. Miscategorized domains can also request to have a category added. This request goes through an approval process with the Cloudflare team.

As part of the domain search results, Cloudflare show the WHOIS details and a history of its category changes over time.

## AS Number

An [AS number ↗](https://www.cloudflare.com/learning/network-layer/what-is-an-autonomous-system/) is a group of IP addresses belonging to and controlled by a single organization. The entire group of networks have a single unified routing policy. The [Internet Assigned Numbers Authority ↗](https://www.iana.org/) (IANA) is the organization responsible for managing the assignment and distribution of AS numbers. The AS number's routing policies are used by [BGP ↗](https://www.cloudflare.com/learning/security/glossary/what-is-bgp/) which is how Cloudflare's [anycast network ↗](https://www.cloudflare.com/learning/cdn/glossary/anycast-network/) works.

When you search for an AS number, Cloudflare will return registration data such as its country, description and type. It will also display data such as domain count, top 10 domains and subnets.

With sufficient data, AS number search results will also return the geographical distribution of traffic in its network, application level attacks and network level attacks, each broken down by Cloudflare mitigation techniques and network protocols, respectively.

## Hash

When you search for a hash, the Cloudflare dashboard will provide a URL report for that specific hash.

To search using a hash:

1. In the Cloudflare dashboard, go to the **Investigate** page.  
[ Go to **Investigate** ](https://dash.cloudflare.com/?to=/:account/security-center/investigate)
2. Enter the hash, then select **Search**.
3. Select **View report** to view the report for your URL.

## URL

When you search for a URL, Cloudflare will provide a list of recent scan reports for that specific URL, limited to the past 30 days. You can view previously generated reports or scan again to generate a new report.

Different Cloudflare plans will have different [scan limitations](https://developers.cloudflare.com/security-center/investigate/scan-limits/).

If you want to scan a URL:

1. In the Cloudflare dashboard, go to the **Investigate** page.  
[ Go to **Investigate** ](https://dash.cloudflare.com/?to=/:account/security-center/investigate)
2. Enter the URL, then select **Search**.

Alternatively, to scan a URL, go to [Cloudflare Radar ↗](https://radar.cloudflare.com/) \> **URL scanner**. Enter the URL, then select **Publish**.

Note

You can use [Cloudflare Radar API](https://developers.cloudflare.com/radar/investigate/url-scanner/#use-the-api) to investigate threats.

### Visibility

When generating a new scan report, the default visibility is set to `Unlisted`, but you have the option to set it to `Public`. By choosing `Public`, the generated scan will be available to all Cloudflare dashboard and Cloudflare Radar users alike, which will increase awareness of potentially malicious websites for others.

We recommend choosing `Unlisted` if you are scanning infrastructure that is not intended to be shared with the wider Cloudflare community.

### Filters

While viewing the most recent scans, you can use the filtering options. Selecting `All account scans` will display both `Unlisted` or `Public` scans initiated from your Cloudflare account. However, by selecting `All global scans`, only `Public` scans are displayed.

### Downloads

You can download a report of your scan in HAR or JSON format.

To download a report:

1. In the Cloudflare dashboard, go to the **Investigate** page.  
[ Go to **Investigate** ](https://dash.cloudflare.com/?to=/:account/security-center/investigate)
2. Enter your domain and select **Search**.
3. Once the report has been generated, select **Download** and choose between **Download HAR** or **Download JSON**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}},{"@type":"ListItem","position":3,"item":{"@id":"/security-center/investigate/","name":"Investigate"}},{"@type":"ListItem","position":4,"item":{"@id":"/security-center/investigate/investigate-threats/","name":"Investigate threats"}}]}
```

---

---
title: Scan limits
description: Limits
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Scan limits

URL scans are limited by search history, Public and Unlisted visibility, and requests per second across different Cloudflare plans.

| Cloudflare Plan    | Search history | Public scans (per month) | Unlisted scans (per month) | Rate limit       |
| ------------------ | -------------- | ------------------------ | -------------------------- | ---------------- |
| **Free / Radar**   | last 50 scans  | 5,000                    | none                       | 1 per 10 seconds |
| **Self serve**     | 30 days        | 5,000                    | 500                        | 1 per 10 seconds |
| **Enterprise**     | 12 months      | 10,000                   | 5,000                      | 12 per second    |
| **Cloudforce One** | Unlimited      | 75,000                   | 20,000                     | 12 per second    |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}},{"@type":"ListItem","position":3,"item":{"@id":"/security-center/investigate/","name":"Investigate"}},{"@type":"ListItem","position":4,"item":{"@id":"/security-center/investigate/scan-limits/","name":"Scan limits"}}]}
```

---

---
title: Brand Protection
description: Detect phishing domains and impersonation attempts targeting your brand.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Brand Protection

Brand Protection allows you to proactively identify and mitigate domain impersonation and phishing attacks. By monitoring newly registered domains and visual assets across the Internet, Cloudflare helps protect your brand's reputation and prevents your customers or employees from submitting sensitive information to fraudulent sites.

Common threats include:

* [Typosquatting ↗](https://en.wikipedia.org/wiki/Typosquatting): For example, typing `cloudfalre.com` instead of `cloudflare.com`.
* Concatenation of services (`cloudflare-service.com`) often registered by attackers to trick unsuspecting victims into submitting private information such as passwords.
* [Homoglyph attacks ↗](https://en.wikipedia.org/wiki/IDN%5Fhomograph%5Fattack) that use lookalike characters to trick unsuspecting victims.

User permission

Access to Brand Protection is managed through [Cloudflare RBAC](https://developers.cloudflare.com/fundamentals/manage-members/roles/).

Only users with the following roles can access and configure Brand Protection:

* Super Admin
* Admin
* Brand Protection (custom role)
* Cloudforce One

## Types of queries

Cloudflare Brand Protection offers two distinct methods for monitoring impersonation: domain search and logo search.

### Domain search

Search for domains based on text patterns, misspellings, or service combinations.

To start searching for new domains that might be trying to impersonate your brand:

1. In the Cloudflare dashboard, go to the **Brand Protection** page.  
[ Go to **Brand protection** ](https://dash.cloudflare.com/?to=/:account/security-center/brand-protection)
2. In **String query**, provide a name for your query. You can add multiple brand phrases on the same query, and the results will generate matches for all of those. Once you entered the string queries, select **Search matches**.
3. In the **Character distance**, select from `0-3`. This defines how many characters a result can differ from your string (for example, a distance of 1 would catch `clpudflare.com`). The number of characters the results can differ from your domain.  
Note  
If a brand phrase or search term has less than five characters, you can only choose a max distance of `0` (zero).
4. You can select **Save query** to monitor it in the future and perform other actions, such as delete, clone and set up alerts, according to your Paid plan limits.
5. To export all matches from a saved query, select your **Query name** \> select the three dots > **Export matches**.

In the section **Monitor Strings**, you can check all the string queries that you selected to monitor. You can delete, clone, or create notifications for a string query. Refer to [Brand Protection Alerts](#brand-protection-alerts) to set up notifications. You can also dismiss any domain matched in the query if you have investigated and deemed it benign or a false positive. Users can still access their previously dismissed matches by turning on the **Show dismissed matches** toggle in the Cloudflare dashboard.

### Logo search (AI-powered)

Logo search uses computer vision to detect domains using your visual assets, even if the domain name does not contain your brand string.

To set up a new logo query:

1. Select **Monitor Logos** and select **Add logo**.
2. Add a name for your query and upload your logo. Only the `.png`, `.jpeg`, and `.jpg` file extensions are supported.
3. Set the threshold: Set a match threshold (the minimum is 75%). A higher score ensures high-precision matches, while a lower score catches remixed or slightly altered versions of your logo.
4. Select **Save logo**. The system will now scan newly detected infrastructure for visual matches.

The browser will return to the **Monitored Logos** page, where you can access your query and configure notifications.

## Investigate a query

In this section, the dashboard displays:

* **Domain overview** where you can request to [change categorization](https://developers.cloudflare.com/security-center/investigate/change-categorization/) and view the resolution history of your domain for up to seven days.
* **WHOIS** that provides details about the date the domain was created, registrant and nameservers.
* **Domain history** that provides information on the domain category and when it was last changed. Refer to [Investigate threats](https://developers.cloudflare.com/security-center/investigate/investigate-threats/) for more details.
* **URL Reports** that provides information on any reported URL.

To investigate a string query:

1. Go to the **Monitor Strings** or **Monitor Logos** section to view all your queries.
2. Select a monitored query to inspect all the domains that matched your query.
3. Next to the domain, select **Domain** or **URL**. This will trigger a search on the [**Investigate**](https://developers.cloudflare.com/security-center/investigate/) section in a separate tab. URL scanner will also be triggered from **Brand Protection** through **Security Center** \> **Investigate**. You will also have access to a report which will be generated automatically. The report will display screenshots of the matched domain, and the registrar of your domain.

## Report abuse

Submit abuse report

You can only submit an abuse report if your domain is with [Cloudflare Registrar ↗](https://www.cloudflare.com/products/registrar/), or if the IP used by the domain is hosted by Cloudflare.

To submit abuse reports directly from the dashboard:

1. In the Cloudflare dashboard, go to the **Brand Protection** page.  
[ Go to **Brand protection** ](https://dash.cloudflare.com/?to=/:account/security-center/brand-protection)
2. Go to **Monitor Strings**, select the query you want to report.
3. Select **Report to Cloudflare**.
4. Fill in the details to submit an abuse report.
5. Select **Submit**.

To view abuse reports, in the Cloudflare dashboard, go to the **Abuse Reports** page.

[ Go to **Abuse reports** ](https://dash.cloudflare.com/?to=/:account/abuse-reports) 

You can review abuse reports against your zones and any mitigations taken against reports in response.

You can also **Request review** of most mitigations.

## Cease and Desist letters

When you identify an infringing domain hosted outside of Cloudflare, you can generate a Cease and Desist (C&D) letter directly from the dashboard. The system automatically pulls registrar data and WHOIS contact information (such as the registrant or registrar abuse email) and pre-fills your custom-branded templates.

When reviewing a matched domain, you have two paths to action depending on where the domain is hosted:

* **Report to Cloudflare**: If the matched domain is using Cloudflare's network or registrar, trigger the integrated abuse reporting flow instantly.
* **Generate a C&D Letter**: If the domain is hosted elsewhere, use one of the default templates or one you previously saved in the dashboard.

### Generate a C&D letter

1. In the Cloudflare dashboard, go to the **Brand Protection** page.  
[ Go to **Brand protection** ](https://dash.cloudflare.com/?to=/:account/security-center/brand-protection)
2. Go to **Monitor Strings** and select a query to view its matched domains.
3. Next to the domain you want to take action on, click **Generate C&D Letter**.
4. Choose a template. You can select from three default templates or from your own saved templates:  
   * **Exact Match**: A formal demand for identical trademark infringements.  
   * **Similar Match**: A standard notice optimized for typosquatting.  
   * **Friendly Tone**: An amicable initial outreach for potential unintentional infringements.
5. Review and edit the pre-filled letter. The system auto-populates recipient data from WHOIS records.
6. Click **Download** to save the finalized PDF.

Note

Cloudflare does not represent you and cannot provide you with legal advice. Only you can decide whether your rights have been infringed, whether a cease and desist letter is appropriate, and what that letter should say.

## Brand Protection API

The [Brand Protection API](https://developers.cloudflare.com/api/resources/brand%5Fprotection/) allows for programmatic management and integration with your [SOC ↗](https://www.cloudflare.com/en-gb/learning/security/glossary/what-is-a-security-operations-center-soc/) or [SIEM ↗](https://www.cloudflare.com/en-gb/learning/security/what-is-siem/). Using the Brand Protection API, you can:

* Manage queries: Create, edit, or delete string and logo queries.
* Data retrieval: Read and download matches for automated ingestion.
* Query editing: Update existing query parameters without losing historical data.

## Notifications and alerts

Brand Protection integrates with Cloudflare's ANS (Alerts Notification Service) to provide configurable alerts when new domains are detected.

Any matches that are found during the new domain search are then inserted into an internal alerts table which triggers an alert for the user. This allows you to receive real-time notifications and take immediate action to investigate and potentially block any suspicious domains that may be attempting to impersonate your brand.

Brand Protection Alerts

**Who is it for?**

Customers who want a summary of activity related to [Brand Protection](https://developers.cloudflare.com/security-center/brand-protection/).

**Other options / filters**

You can set up Brand Protection Alerts on individual monitored queries. For more details, refer to [Brand Protection Alerts](https://developers.cloudflare.com/security-center/brand-protection/#brand-protection-alerts).

**Included with**

Professional plans or higher.

**What should you do if you receive one?**

Investigate and potentially block any suspicious domains that may be trying to impersonate your brand.

Brand Protection Digest

**Who is it for?**

Customers who want a summary of activity related to [Brand Protection](https://developers.cloudflare.com/security-center/brand-protection/).

**Other options / filters**

You can set up Brand Protection Digest on individual monitored queries. For more details, refer to [Brand Protection Alerts](https://developers.cloudflare.com/security-center/brand-protection/#brand-protection-alerts).

**Included with**

Professional plans or higher.

**What should you do if you receive one?**

Investigate and potentially block any suspicious domains that may be trying to impersonate your brand.

Logo Match Alerts

**Who is it for?**

Customers who want to receive a notification when the [Brand Protection](https://developers.cloudflare.com/security-center/brand-protection/) system detects a new domain which is using the uploaded logo and might be infringing copyright.

**Other options / filters**

You can select the query that you want to be alerted on.

**Included with**

Enterprise plans.

**What should you do if you receive one?**

Review the domains and URLs that are potentially impersonating your brand.

Security Insights

**Who is it for?**

Customers who want to receive notifications based on security insights findings.

**Other options / filters**

You can select the insight(s) you want to be alerted on.

**Included with**

All Cloudflare plans.

**What should you do if you receive one?**

Review the insight and decide whether you want to resolve it, archive it, or export it.

Abuse report

**Who is it for?**

Customers who want to be alerted in the event that an abuse report is filed against their website.

**Other options / filters**

You can filter the reports based on date, report status, report type, and domain.

**Included with**

All Cloudflare plans.

**What should you do if you receive one?**

View our guidance on [customer abuse report obligations](https://developers.cloudflare.com/fundamentals/reference/report-abuse/abuse-report-obligations/) and more information on how to [view and submit abuse reports](https://developers.cloudflare.com/fundamentals/reference/report-abuse/submit-report/).

To set up a Brand Protection Alert:

1. Go to **Monitor Strings** and locate the query for which you would like to create notifications.
2. Select **alerts**. This should redirect you to the **Add Notification** page, where you can configure what you want to be notified about, and how.  
Note  
You can also set up the alerts from your [Notifications](https://developers.cloudflare.com/notifications/) menu.
3. Create a notification name, add a description (optional), and select the monitored queries. You can also add a Webhook, and a notification email. You can add multiple email addresses.
4. Select **Save**.

Manage your notifications in the **All notifications** tab. You can disable, edit, delete, or test them.

## Subscriptions and limitations

* Self-serve users can subscribe directly to add monitoring capacity to their account.
* You may only use the Brand Protection search tools to search for domains that may be attempting to impersonate your brand or a brand that has authorized you to conduct such search on its behalf.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}},{"@type":"ListItem","position":3,"item":{"@id":"/security-center/brand-protection/","name":"Brand Protection"}}]}
```

---

---
title: Custom Indicator Feeds
description: Receive curated threat intelligence feeds from Cyber Defense Collaboration groups.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Custom Indicator Feeds

Cloudflare's threat intelligence team crowdsources attack trends and protects users automatically, such as from zero-day vulnerabilities like the [HTTP/2 Rapid Reset attack ↗](https://blog.cloudflare.com/technical-breakdown-http2-rapid-reset-ddos-attack/). However, in some cases, Cloudflare will partner with external entities that have their own feeds which can be shared with eligible Cloudflare users.

With Custom Indicator Feeds, Cloudflare provides a threat intelligence feed based on data received from various Cyber Defense Collaboration groups. The security filtering capabilities are available to eligible public and private sector organizations.

## Publicly available feeds

Cloudflare provides some feeds to Gateway users without the need to establish a provider relationship.

| Name                                                                                                                                                    | Description                                                                                                                                                                         | Availability                              |
| ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
| [Treasury Early Indicator Feed ↗](https://www.cloudflare.com/press-releases/2024/us-department-of-treasury-pnnl-finserv-threat-intel-feed/), Feed ID 14 | Threat data for financial institutions provided by the US Department of Treasury and Pacific Northwest National Laboratory (PNNL). For more information, contact your account team. | Approved financial services organizations |
| [UK NCSC Public Threat Indicators ↗](https://www.ncsc.gov.uk/information/pdns) Feed ID 24                                                               | Recursive DNS service supplied by the UK National Cyber Security Centre (NCSC) to block DNS-based malware.                                                                          | All users                                 |
| Cloudforce One - Public Feed Feed ID 34                                                                                                                 | Feed of indicators.                                                                                                                                                                 | All users                                 |

## Get started

Cloudflare threat intelligence data consists of a data exchange between providers and subscribers.

A provider is an organization that has a set of data that they are interested in sharing with other Cloudflare organizations. Any organization can be a provider. Examples of current providers are Government Cyber Defense groups.

Subscribers can be any Cloudflare customer that wants to secure their environment further by creating rules based on provider datasets. Subscribers must be authorized by a provider. Authorization is granted using the [Grant permission to indicator feed endpoint](https://developers.cloudflare.com/api/resources/intel/subresources/indicator%5Ffeeds/subresources/permissions/methods/create/).

If your organization is interested in becoming a provider or a subscriber, contact your account team.

### Create a Custom Indicator Feed

Providers can create and manage a Custom Indicator Feed with the [Custom Indicator Feeds API endpoints](https://developers.cloudflare.com/api/resources/intel/subresources/indicator%5Ffeeds/methods/list/):

1. Contact your account team to configure your account as an indicator feed provider.
2. Create a feed with the [Create new indicator feed endpoint](https://developers.cloudflare.com/api/resources/intel/subresources/indicator%5Ffeeds/methods/create/). Make note of the `feed_id` generated for your feed. For example:  
Create new indicator feed  
```  
curl "https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/intel/indicator-feeds" \  
  --header 'Content-Type: application/json' \  
  --header 'X-Auth-Email: <EMAIL>' \  
  --header 'X-Auth-Key: <API_KEY>' \  
  --data '{  
  "description": "Custom indicator feed to detect threats",  
  "name": "threat_indicator_feed"  
}'  
```  
```  
{  
  "result": {  
    "id": 10,  
    "name": "threat_indicator_feed",  
    "description": "Custom indicator feed to detect threats",  
    "created_on": "2024-09-17T21:16:09.412Z",  
    "modified_on": "2024-09-17T21:16:09.412Z"  
  },  
  "success": true,  
  "errors": [],  
  "messages": []  
}  
```
3. Upload data to the feed with the [Update indicator feed data endpoint](https://developers.cloudflare.com/api/resources/intel/subresources/indicator%5Ffeeds/subresources/snapshots/methods/update/). Uploaded indicator data must be in a [.stix2 ↗](https://oasis-open.github.io/cti-documentation/stix/intro) formatted file. The [maximum upload file size](https://developers.cloudflare.com/r2/platform/limits/) is 4.995 GiB.  
Update indicator feed data  
```  
curl --request PUT \  
  "https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/intel/indicator-feeds/<FEED_ID>/snapshot" \  
  --header 'Content-Type: multipart/form-data' \  
  --header 'X-Auth-Email: <EMAIL>' \  
  --header 'X-Auth-Key: <API_KEY>' \  
  --form 'source=@/path/to/file'  
```  
```  
{  
  "result": {  
    "file_id": 1,  
    "filename": "snapshot_file.unified",  
    "status": "unified"  
  },  
  "errors": [],  
  "messages": [],  
  "success": true  
}  
```  
Note  
Indicator feeds use a snapshot system. To update feeds with new data, providers must upload a file containing all previous and new indicators.
4. (Optional) Verify the status of your feed upload with the [Get indicator feed data endpoint](https://developers.cloudflare.com/api/resources/intel/subresources/indicator%5Ffeeds/methods/data/). For example:  
Get indicator feed data  
```  
curl --request GET \  
  "https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/intel/indicator-feeds/<FEED_ID>/data" \  
  --header 'Content-Type: application/json' \  
  --header 'X-Auth-Email: <EMAIL>' \  
  --header 'X-Auth-Key: <API_KEY>'  
```  
```  
{  
  "result": {  
    "id": 10,  
    "name": "threat_indicator_feed",  
    "description": "Custom indicator feed to detect threats",  
    "created_on": "2023-08-01T18:00:26.65715Z",  
    "modified_on": "2023-08-01T18:00:26.65715Z",  
    "latest_upload_status": "Complete"  
  },  
  "success": true,  
  "errors": [],  
  "messages": []  
}  
```
5. Grant access to subscribers with the [Grant permission to indicator feed endpoint](https://developers.cloudflare.com/api/resources/intel/subresources/indicator%5Ffeeds/subresources/permissions/methods/create/). You can add subscribers to the feed's allowed subscribers list using their [account IDs](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/). For example:  
Update indicator feed data  
```  
curl --request PUT \  
  "https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/intel/indicator-feeds/<FEED_ID>/snapshot" \  
  --header 'Content-Type: multipart/form-data' \  
  --header 'X-Auth-Email: <EMAIL>' \  
  --header 'X-Auth-Key: <API_KEY>' \  
  --data '{  
  "account_tag": "823f45f16fd2f7e21e1e054aga4d2859",  
  "feed_id": 10  
}'  
```

### Use a feed in Gateway

Once an account is granted access to a feed, it will be available to match traffic as a [selector in Gateway DNS policies](https://developers.cloudflare.com/cloudflare-one/traffic-policies/dns-policies/#indicator-feeds).

1. In [Cloudflare One ↗](https://one.dash.cloudflare.com/), go to **Traffic policies** \> **Firewall policies**. Select **DNS**.
2. To create a new DNS policy, select **Add a policy**.
3. Name your policy.
4. In **Traffic**, add a condition with the **Indicator Feeds** selector. If your account has been granted access to a Custom Indicator Feed, Gateway will list the feed in **Value**. For example, you can block sites that appear in a feed:  
| Selector        | Operator | Value               | Action |  
| --------------- | -------- | ------------------- | ------ |  
| Indicator Feeds | in       | _Threat Intel Feed_ | Block  |
5. Select **Create policy**.

For more information on creating Gateway policies, refer to [DNS policies](https://developers.cloudflare.com/cloudflare-one/traffic-policies/dns-policies/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}},{"@type":"ListItem","position":3,"item":{"@id":"/security-center/indicator-feeds/","name":"Custom Indicator Feeds"}}]}
```

---

---
title: Changelog
description: Track the latest updates and changes to Security Center features.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/security-center/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Changelog

[ Subscribe to RSS ](https://developers.cloudflare.com/changelog/rss/security-center.xml) 

## 2026-06-10

  
**Automated Cease and Desist templates for Brand Protection**   

**TL;DR:** Brand Protection now features an **Automated Cease & Desist (C&D)** workflow. When you discover an infringing domain hosted outside of Cloudflare, you can instantly generate, review, and download a custom-branded, pre-filled legal notice in seconds.

#### Why this matters

This update introduces a major shift from pure detection to actionable enforcement, eliminating the manual burden for your Trust & Safety and Legal teams:

* **Instant WHOIS and Recipient Lookup:** We automatically scrape registrar data and WHOIS contact information (such as the registrant or registrar abuse email) behind the scenes, highlighting exactly where your notice needs to be sent
* **Smart Template Automation:** We pre-fill your custom-branded templates with essential metadata, including the infringing domain, registrar name, and discovery date.
* **Tailored Enforcement Tones:** Choose from three default layout strategies depending on the severity of the infrastructure match:  
   * _Exact Match:_ A formal demand for identical trademark infringements  
   * _Similar Match:_ A standard notice optimized for typosquatting (one-character distance matches)  
   * _Friendly Tone:_ An amicable initial outreach for potential unintentional or accidental infringements
* **Full Editing Control:** Before creating the final PDF, a real-time review screen allows you to fine-tune the messaging, modify placeholders, and ensure your text aligns perfectly with internal legal standards

#### How it works

When reviewing a malicious domain match inside your dashboard, your enforcement path splits depending on where the attacker is located:

1. **On the Cloudflare Network:** If the domain uses Cloudflare’s network or registrar, trigger our existing integrated abuse reporting flow with one click.
2. **Hosted Elsewhere:** If the domain is hosted on an external provider, click the **Generate C&D Letter** option to launch the new document builder, pick your template, verify the auto-populated recipient data, and download your finalized PDF.

You can manage your templates and enforce matches by going to the **Cloudflare Dashboard > Application Security > Brand Protection** and selecting your detected Brand Protection matches. For more information, read the [Brand Protection documentation](https://developers.cloudflare.com/security-center/brand-protection/).

> **Note:** Cloudflare does not represent you and cannot provide you with legal advice. Only you can decide whether your rights have been infringed, whether a cease and desist letter is appropriate, and what that letter should say.

## 2026-06-08

  
**Create WAF rules directly from Threat Events saved views**   

Cloudforce One users can now turn [Threat Events indicators](https://developers.cloudflare.com/security-center/cloudforce-one/#analyze-threat-events) into active defense. With this update, users can instantly generate a WAF rule that matches the dynamic list of IP addresses returned by any of their **Saved Views**.

#### Why this matters

Threat intelligence is most effective when it is immediately actionable. Previously, blocking threat actors required manually extracting indicators from threat events and copying them into your firewall rules. This new integration bridges the gap between threat discovery and threat mitigation:

* When you identify an active threat pattern - such as an ongoing campaign targeting a specific industry, or using a known indicator type - you can pivot from investigation to mitigation in a single click.
* Instead of writing complex, static IP rules, this functionality allows you to leverage the specific filtering logic you have already defined and saved within your Threat Events ecosystem.
* Automating the generation of the WAF rule expression from your threat views eliminates manual copying errors, ensuring that the right malicious infrastructure is blocked instantly.

#### How to use it

You can implement these rules through both the dashboard UI and via the API / Terraform.

Go to **Cloudflare Dashboard** \> **Application Security** \> **Threat Intelligence** \> **Manage Views**, select your desired view, and select **Create WAF Rule**.

This will automatically pre-populate the [WAF rule builder](https://developers.cloudflare.com/firewall/cf-dashboard/create-edit-delete-rules/) with the matching threat event IP indicators.

You can also automate this workflow by utilizing the [**WAF Rule Builder API**](https://developers.cloudflare.com/firewall/api/cf-firewall-rules/) alongside your [Threat Events saved views endpoints](https://developers.cloudflare.com/firewall/api/cf-firewall-rules/).

## 2026-06-08

  
**Introducing Threat Actor Profiles in Threat Events**   

**TL;DR:** We’ve launched **Threat Actor Profiles** directly inside the Threat Events dashboard. You can now immediately pivot from a generic alert or blocked event to a profile that unmasks the "Who, Why, and How" behind a threat event.

#### Why this matters

Security teams often suffer from a visibility gap. When an attack is blocked, it's difficult to know if it was a random automated bot or a sophisticated advanced persistent threat (APT) campaign specifically targeting your industry. Finding out usually means leaving your security dashboard to hunt through external OSINT feeds or static, out-of-date threat reports. Threat Actor Profiles solve this by sharing Cloudforce One’s deep adversary research directly inside your workflow:

* Cloudflare sees the traffic in real-time across approximately 20% of the web. This means actor profiles display active malicious infrastructure the moment it touches our global edge.
* Every profile provides clear strategic and tactical modules including alternative aliases, origin tracking, historical threat event volume, and MITRE ATT&CK mapping detailing the adversary's technical methods.
* You can search the dedicated threat actor directory or click an actor's name inside any threat event to view all details and related events to the specific threat actor.

#### How to use it

Adversary tracking is now available in the Cloudflare Dashbboard and ready to be included in your daily investigation workflow:

* Click on the **Threat Actor** name in the Threat Events table to open their full identity profile and review their aliases and attack stats.
* Navigate to **Cloudflare Dashboard > Application Security > Threat Intelligence** to explore the new **Threat Actors** tab. Here, you can browse a card-based directory of all established entities tracked by Cloudforce One.

Learn more in the [Cloudforce One documentation ↗](https://developers.cloudflare.com/security-center/cloudforce-one/#identify-the-adversary).

## 2026-05-29

  
**Security scans more frequent**   

Security Insights scans now run more often. Cloudflare scans Free accounts **every 7 days**, Pro and Business accounts **every 3 days**, and Enterprise accounts **daily**.

In addition, all accounts and zones now receive scans by default. You no longer need to enable scans before Cloudflare checks your account for misconfigurations, vulnerabilities, and other security risks.

Granular on-demand scans are now available on any plan. You can trigger an on-demand scan for any zone, insight, insight type from the Cloudflare dashboard in order to quickly re-check your security posture after remediating an issue.

To learn more, refer to the [Security Insights documentation](https://developers.cloudflare.com/security/security-insights/).

## 2026-05-12

  
**Agent Readiness scores now available in URL Scanner via the Cloudflare Dashboard**   

We’ve added a new **Agent Readiness** tab to URL Scanner reports accessible via the Cloudflare dashboard. This feature evaluates your site against emerging AI standards and provides six specialized scores to help you optimize for the next generation of AI agents and automated discovery.

The Internet is shifting from a human-read web to a machine-read web. AI agents now browse, interact with, and even perform transactions on websites. If a site isn't "agent-ready," these bots may consume excessive bandwidth, fail to find critical information, or be unable to navigate your services efficiently.

This update provides material value by breaking down readiness into six actionable categories:

* **Basic Web Presence**
* **Discoverability**
* **Content Accessibility**
* **Bot Access Control**
* **Protocol Discovery**
* **Commerce**

#### Accessing the report

You can view these scores for any scanned URL directly in the dashboard or via our API.

* **Dashboard:** Go to **Protect & Connect > Application Security > Investigate**. After running a scan, select the **Agent Readiness** tab in the report.
* **API:** Use the [URL Scanner API ↗](https://developers.cloudflare.com/radar/investigate/url-scanner/) to programmatically retrieve these scores for your infrastructure.

To learn more about the methodology behind these scores, refer to the [blogpost ↗](https://blog.cloudflare.com/agent-readiness/).

## 2026-05-07

  
**CSV export and adjustable page density for RFIs**   

You can now export your Requests for Information (RFI) history to a **CSV document** and customize your dashboard view by choosing how many RFI records to load per page.

#### Why this matters

These quality-of-life updates focus on data portability and dashboard performance, allowing power users to manage high volumes of requests more efficiently:

* The new **CSV export** allows you to move RFI data into external tools for custom reporting, internal auditing, or cross-referencing with other security projects without manual data entry
* With **adjustable page density**, you can now choose to load more records at once (10, 25 or 50) to scan through history faster

Cloudforce One subscribers can find these new options in [Cloudflare Dashboard > Application Security > Threat Intelligence > Requests for Information ↗](https://dash.cloudflare.com/?to=/:account/application-security/threat-intelligence/requests).

## 2026-05-06

  
**TAXII support added to Threat Events API**   

The Cloudforce One Threat Events API now supports [**TAXII** ↗](https://www.cloudflare.com/en-gb/learning/security/what-is-stix-and-taxii/) as an output format, enabling standardized, automated sharing of cyber threat intelligence with your existing security stack.

#### Why this matters

* You can now ingest Cloudforce One threat data directly into your SIEM, TIP or SOAR tools that prefer TAXII-formatted streams without needing custom translation scripts.
* By supporting the TAXII format parameter in our API, security teams can automate the synchronization of indicator data, reducing the manual overhead of updating blocklists and detection rules.
* This alignment with industry standards ensures that your threat data remains consistent across different security ecosystems and partner integrations.

#### How to use it

When calling the Threat Events API, you can now specify `taxii` in the `format` query parameter:

`GET /accounts/{account_id}/cloudforce_one/threat_events?format=taxii`

You can find the updated documentation in the [Cloudflare API Reference ↗](https://developers.cloudflare.com/api/resources/cloudforce%5Fone/subresources/threat%5Fevents/methods/list#%28resource%29%20cloudforce%5Fone.threat%5Fevents%20%3E%20%28method%29%20list%20%3E%20%28params%29%20default%20%3E%20%28param%29%20format%20%3E%20%28schema%29).

## 2026-04-27

  
**Unified workspace for Brand Protection**   

We have introduced a unified investigation workspace within Brand Protection to help analysts manage complex brand portfolios. Instead of jumping between individual queries, you can now consolidate your workflow into a single, cohesive view.

#### What's new

* You can now elect multiple saved queries from your dashboard to generate a consolidated "Combined Matches" view. This allows you to triage results from different brand queries in one unified table
* You can open query extended views in distinct tabs within the Brand Protection dashboard. This enables you to maintain multiple investigation contexts simultaneously and switch between them without losing your place.
* You can reset your workspace using the new "Clear Selection" action, making it easier to pivot between different investigation sets.

#### Key benefits

* Eliminate fragmented workflows by viewing all matches across different query buckets in a single table, reducing the need to click through dozens of individual query pages
* Correlate related campaigns by seeing similar domains or infrastructure patterns that appear across multiple saved queries

Learn more in our [Brand Protection documentation](https://developers.cloudflare.com/security-center/brand-protection/).

## 2026-04-08

  
**Real-time alerts and daily digests for Threat Events**   

You can now automate your threat monitoring by setting up custom alerts in your saved views. Instead of manually checking the dashboard for updates, you can subscribe to notifications that trigger whenever new data matches your specific filter sets, like new activity associated to a particular threat actor or spikes in activity within your industry.

#### Stay ahead of emerging threats

By linking your saved views to the Cloudflare Notifications Center, you can ensure the right information reaches your team at the right time.

* **Immediate Alerts**: receive real-time notifications the moment a critical event is detected that matches your saved criteria. This is essential for high-priority monitoring, such as tracking active campaigns from specific APT groups.
* **Daily Digests**: opt for a summarized report delivered once a day. This is ideal for maintaining situational awareness of broader trends, like regional activity shifts or industry-wide threat landscapes, without cluttering your inbox.
![Threat Events notifications](https://developers.cloudflare.com/_astro/threat-events-notifications.3Fl8LGOn_S9A1r.webp) 

#### How to get started

To set up an alert, go to **Application Security** \> **Threat Intelligence** \> **Threat Events**. From there:

1. Choose your datasets and apply your desired filters and select **Save View** (or select an existing one).
2. Open the **Manage Saved Views** menu.
3. Select **Add Alert** next to your chosen view to configure your notification preferences in the Cloudflare dashboard.

For more technical details on configuring notifications, refer to the [Threat Events documentation](https://developers.cloudflare.com/security-center/cloudforce-one/).

## 2026-03-18

  
**Real-time logo match preview**   

We are introducing **Logo Match Preview**, bringing the same pre-save visibility to visual assets that was previously only available for string-based queries. This update allows you to fine-tune your brand detection strategy before committing to a live monitor.

#### What’s new:

* Upload your brand logo and immediately see a sample of potential matches from recently detected sites before finalizing the query
* Adjust your similarity score (from 75% to 100%) and watch the results refresh in real-time to find the balance between broad detection and noise reduction
* Review the specific logos triggered by your current settings to ensure your query is capturing the right level of brand infringement

If you are ready to test your brand assets, go to the [Brand Protection dashboard ↗](https://developers.cloudflare.com/security-center/brand-protection/) to try the new preview tool.

## 2026-03-06

  
**Dismiss and filter matches in Brand Protection**   

We have introduced new triage controls to help you manage your Brand Protection results more efficiently. You can now clear out the noise by dismissing matches while maintaining full visibility into your historical decisions.

#### What's new

* **Dismiss matches**: Users can now mark specific results as dismissed if they are determined to be benign or false positives, removing them from the primary triage view.
* **Show/Hide toggle**: A new visibility control allows you to instantly switch between viewing only active matches and including previously dismissed ones.
* **Persistent review states**: Dismissed status is saved across sessions, ensuring that your workspace remains organized and focused on new or high-priority threats.

#### Key benefits of the dismiss match functionality:

* Reduce alert fatigue by hiding known-safe results, allowing your team to focus exclusively on unreviewed or high-risk infringements.
* Auditability and recovery through the visibility toggle, ensuring that no match is ever truly "lost" and can be re-evaluated if a site's content changes.
* Improved collaboration as your team members can see which matches have already been vetted and dismissed by others.

Ready to clean up your match queue? Learn more in our [Brand Protection documentation](https://developers.cloudflare.com/security-center/brand-protection/).

## 2026-02-23

  
**Saved views for Threat Events**   

**TL;DR:** You can now create and save custom configurations of the Threat Events dashboard, allowing you to instantly return to specific filtered views — such as industry-specific attacks or regional Sankey flows — without manual reconfiguration.

#### Why this matters

Threat intelligence is most effective when it is personalized. Previously, analysts had to manually re-apply complex filters (like combining specific industry datasets with geographic origins) every time they logged in. This update provides material value by:

* Analysts can now jump straight into "Known Ransomware Infrastructure" or "Retail Sector Targets" views with a single click, eliminating repetitive setup tasks
* Teams can ensure everyone is looking at the same data subsets by using standardized saved views, reducing the risk of missing critical patterns due to inconsistent filtering.

Cloudforce One subscribers can start saving their custom views now in [Application Security > Threat Intelligence > Threat Events ↗](https://dash.cloudflare.com/?to=/:account/security-center/threat-intelligence/threat-events).

## 2026-02-19

  
**Cloudforce One Threat events graphs are now visible in the dashboard**   

We have introduced dynamic visualizations to the Threat Events dashboard to help you better understand the threat landscape and identify emerging patterns at a glance.

What's new:

* **Sankey Diagrams**: Trace the flow of attacks from country of origin to target country to identify which regions are being hit hardest and where the threat infrastructure resides.
![Sankey Diagram](https://developers.cloudflare.com/_astro/2026-02-19-sankey-diagram.VZMSmdZL_Z1dxq3E.webp) 
* **Dataset Distribution over time**: Instantly pivot your view to understand if a specific campaign is targeting your sector or if it is a broad-spectrum commodity attack.
![Events over time](https://developers.cloudflare.com/_astro/2026-02-19-events-over-time.CqD7VKqA_Z20JNi0.webp) 
* **Enhanced Filtering**: Use these visual tools to filter and drill down into specific attack vectors directly from the charts.

Cloudforce One subscribers can explore these new views now in [Application Security > Threat Intelligence > Threat Events ↗](https://dash.cloudflare.com/?to=/:account/security-center/threat-intelligence/threat-events).

## 2026-02-12

  
**Enhanced Logo Matching for Brand Protection**   

We have significantly upgraded our Logo Matching capabilities within Brand Protection. While previously limited to approximately 100% matches, users can now detect a wider range of brand assets through a redesigned matching model and UI.

#### What's new

* **Configurable match thresholds**: Users can set a minimum match score (starting at 75%) when creating a logo query to capture subtle variations or high-quality impersonations.
* **Visual match scores**: Allow users to see the exact percentage of the match directly in the results table, highlighted with color-coded lozenges to indicate severity.
* **Direct logo previews**: Available in the Cloudflare dashboard — similar to string matches — to verify infringements at a glance.

#### Key benefits

* **Expose sophisticated impersonators** who use slightly altered logos to bypass basic detection filters.
* **Faster triage** of the most relevant threats immediately using visual indicators, reducing the time spent manually reviewing matches.

Ready to protect your visual identity? Learn more in our [Brand Protection documentation](https://developers.cloudflare.com/security-center/brand-protection/).

## 2026-02-03

  
**Threat actor identification with "also known as" aliases**   

Identifying threat actors can be challenging, because naming conventions often vary across the security industry. To simplify your research, **Cloudflare Threat Events** now include an **Also known as** field, providing a list of common aliases and industry-standard names for the groups we track.

This new field is available in both the Cloudflare dashboard and via the API. In the dashboard, you can view these aliases by expanding the event details side panel (under the **Attacker** field) or by adding it as a column in your configurable table view.

#### Key benefits

* Easily map Cloudflare-tracked actors to the naming conventions used by other vendors without manual cross-referencing.
* Quickly identify if a detected threat actor matches a group your team is already monitoring via other intelligence feeds.

For more information on how to access this data, refer to the [Threat Events API documentation ↗](https://developers.cloudflare.com/api/resources/cloudforce%5Fone/subresources/threat%5Fevents/).

## 2026-01-14

  
**URL Scanner now supports PDF report downloads**   

We have expanded the reporting capabilities of the Cloudflare URL Scanner. In addition to existing JSON and HAR exports, users can now generate and download a **PDF report** directly from the Cloudflare dashboard. This update streamlines how security analysts can share findings with stakeholders who may not have access to the Cloudflare dashboard or specialized tools to parse JSON and HAR files.

**Key Benefits:**

* Consolidate scan results, including screenshots, security signatures, and metadata, into a single, portable document
* Easily share professional-grade summaries with non-technical stakeholders or legal teams for faster incident response

**What’s new:**

* **PDF Export Button:** A new download option is available in the URL Scanner results page within the Cloudflare dashboard
* **Unified Documentation:** Access all scan details—from high-level summaries to specific security flags—in one offline-friendly file

To get started with the URL Scanner and explore our reporting capabilities, visit the [URL Scanner API documentation ↗](https://developers.cloudflare.com/api/resources/url%5Fscanner/).

---

## 2026-01-12

  
**Cloudflare Threat Events now support STIX2 format**   

We are excited to announce that **Cloudflare Threat Events** now supports the **STIX2 (Structured Threat Information Expression)** format. This was a highly requested feature designed to streamline how security teams consume and act upon our threat intelligence.

By adopting this industry-standard format, you can now integrate Cloudflare's threat events data more effectively into your existing security ecosystem.

#### Key benefits

* Eliminate the need for custom parsers, as STIX2 allows for "out of the box" ingestion into major **Threat Intel Platforms (TIPs)**, **SIEMs**, and **SOAR** tools.
* STIX2 provides a standardized way to represent relationships between indicators, sightings, and threat actors, giving your analysts a clearer picture of the threat landscape.

For technical details on how to query events using this format, please refer to our [Threat Events API Documentation ↗](https://developers.cloudflare.com/api/resources/cloudforce%5Fone/subresources/threat%5Fevents/methods/list/).

---

## 2025-11-21

  
**Threat insights are now available in the Threat Events platform**   

The threat events platform now has threat insights available for some relevant parent events. Threat intelligence analyst users can access these insights for their threat hunting activity. Insights are also highlighted in the Cloudflare dashboard by a small `lightning icon` and the insights can refer to multiple, connected events, potentially part of the same attack or campaign and associated with the same threat actor.

For more information, refer to [Analyze threat events](https://developers.cloudflare.com/security-center/cloudforce-one/#analyze-threat-events).

## 2025-10-31

  
**Report logo misuse to Cloudflare directly from the Brand Protection dashboard**   

The Brand Protection logo query dashboard now allows you to use the **Report to Cloudflare** button to submit an Abuse report directly from the Brand Protection logo queries dashboard. While you could previously report new domains that were impersonating your brand before, now you can do the same for websites found to be using your logo without your permission. The abuse reports will be prefilled and you will only need to validate a few fields before you can click the submit button, after which our team process your request.

Ready to start? Check out the [Brand Protection docs](https://developers.cloudflare.com/security-center/brand-protection/).

## 2025-10-27

  
**Cloudforce One RFI tokens are now visible in the dashboard**   

The Requests for Information (RFI) dashboard now shows users the number of tokens used by each submitted RFI to better understand usage of tokens and how they relate to each request submitted.

![Cloudforce One RFI tokens](https://developers.cloudflare.com/_astro/2025-10-24RFITokens.DPm1e8uC_2g3fE3.webp) 

What’s new:

* Users can now see the number of tokens used for a submitted request for information.
* Users can see the remaining tokens allocated to their account for the quarter.
* Users can only select the Routine priority for the `Strategic Threat Research` request type.

Cloudforce One subscribers can try it now in [Application Security > Threat Intelligence > Requests for Information ↗](https://dash.cloudflare.com/?to=/:account/security-center/threat-intelligence/requests).

## 2025-10-17

  
**New Application Security reports (Closed Beta)**   

Cloudflare's new **Application Security report**, currently in Closed Beta, is now available in the dashboard.

[ Go to **Security reports** ](https://dash.cloudflare.com/?to=/:account/security-center/reports) 

The reports are generated monthly and provide cyber security insights trends for all of the Enterprise zones in your Cloudflare account.

The reports also include an industry benchmark, comparing your cyber security landscape to peers in your industry.

![Application Security report mock data](https://developers.cloudflare.com/_astro/2025-10-17-application-security-report-mock-data.Cz0-WuoX_15MbLt.webp) 

Learn more about the reports by referring to the [Security Reports documentation](https://developers.cloudflare.com/analytics/account-and-zone-analytics/app-security-reports/).

Use the feedback survey link at the top of the page to help us improve the reports.

![Application Security report survey](https://developers.cloudflare.com/_astro/2025-10-17-report-feedback-survey.DPmUlWh2_Z1nYBN6.webp) 

## 2025-08-15

  
**Save time with bulk query creation in Brand Protection**   

[Brand Protection](https://developers.cloudflare.com/security-center/brand-protection/) detects domains that may be impersonating your brand — from common misspellings (`cloudfalre.com`) to malicious concatenations (`cloudflare-okta.com`). Saved search queries run continuously and alert you when suspicious domains appear.

You can now create and save multiple queries in a single step, streamlining setup and management. Available now via the [Brand Protection bulk query creation API](https://developers.cloudflare.com/api/resources/brand%5Fprotection/subresources/queries/methods/bulk/).

## 2025-07-18

  
**New APIs for Brand Protection setup**   

The Brand Protection API is now available, allowing users to create new queries and delete existing ones, fetch matches and more!

What you can do:

* **create new string or logo query**
* **delete string or logo queries**
* **download matches for both logo and string queries**
* **read matches for both logo and string queries**

Ready to start? Check out the [Brand Protection API](https://developers.cloudflare.com/api/resources/brand%5Fprotection/) in our documentation.

## 2025-05-08

  
**URL Scanner now supports geo-specific scanning**   

Enterprise customers can now choose the geographic location from which a URL scan is performed — either via [Security Center](https://developers.cloudflare.com/security-center/investigate/) in the Cloudflare dashboard or via the [URL Scanner API](https://developers.cloudflare.com/api/resources/url%5Fscanner/subresources/scans/methods/create/).

This feature gives security teams greater insight into how a website behaves across different regions, helping uncover targeted, location-specific threats.

**What’s new:**

* Location Picker: Select a location for the scan via **Security Center → Investigate** in the dashboard or through the API.
* Region-aware scanning: Understand how content changes by location — useful for detecting regionally tailored attacks.
* Default behavior: If no location is set, scans default to the user’s current geographic region.

Learn more in the [Security Center documentation](https://developers.cloudflare.com/security-center/).

## 2025-02-03

* Security Center now has a role called Brand Protection. This role gives you access to the Brand Protection feature on the API and Cloudflare dashboard. Brand Protection role also gives you access to the Investigate platform, where you can consume the Threat Intel API and URL scanner API calls.

## 2025-01-20

* On the URL scanner, customers who search for a report will now get a list of all reports related to that specific hostname. A hash is also available in the security report. By selecting the hash, the dashboard will list reports containing the same hash.

## 2024-09-23

* Customers can now export all matches from a saved query. Select your **Query name** \> select the three dots > **Export matches**.

## 2024-09-19

* Customers can now create a `security.txt` file file to provide the security research team with a standardized way to report vulnerabilities.

## 2024-07-22

* Customers can now archive multiple Security Insights at the same time. Go to **Security Center** \> **Security Insights** and select the insights to archive.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/security-center/","name":"Security Center"}},{"@type":"ListItem","position":3,"item":{"@id":"/security-center/changelog/","name":"Changelog"}}]}
```

---

---
title: Cloudflare Turnstile
description: Verify visitors are human with a CAPTCHA-free, privacy-preserving alternative.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Cloudflare Turnstile

Cloudflare's smart CAPTCHA alternative.

Turnstile can be embedded into any website without sending traffic through Cloudflare and works without showing visitors a CAPTCHA.

Cloudflare issues challenges through the [Challenge Platform](https://developers.cloudflare.com/cloudflare-challenges/), which is the same underlying technology powering [Turnstile](https://developers.cloudflare.com/turnstile/).

In contrast to our Challenge page offerings, Turnstile allows you to run challenges anywhere on your site in a less-intrusive way without requiring the use of Cloudflare's CDN.

## How Turnstile works

![Turnstile Overview](https://developers.cloudflare.com/_astro/turnstile-overview.BlA8uXVD_2tsm0o.webp) 

Turnstile adapts the challenge outcome to the individual visitor or browser. First, we run a series of small non-interactive JavaScript challenges to gather signals about the visitor or browser environment.

These challenges include proof-of-work (computational puzzles), proof-of-space, probing for web APIs, and various other challenges for detecting browser-quirks and human behavior. As a result, we can fine-tune the difficulty of the challenge to the specific request and avoid showing a visual or interactive puzzle to a user.

Note

For detailed information on Turnstile's data privacy practices, refer to the [Turnstile Privacy Addendum ↗](https://www.cloudflare.com/turnstile-privacy-policy/).

### Widget types

Turnstile [widget types](https://developers.cloudflare.com/turnstile/concepts/widget/) include:

* **Managed** (recommended): Automatically decides whether to show a checkbox based on visitor risk level.
* **Non-interactive**: Visitors never need to interact with the widget.
* **Invisible**: The widget is completely hidden from the visitor.

---

## Accessibility

Turnstile is WCAG 2.2 AA compliant.

---

## Features

###  Turnstile Analytics 

Assess the number of challenges issued, evaluate the [challenge solve rate](https://developers.cloudflare.com/cloudflare-challenges/reference/challenge-solve-rate/), and view the metrics of issued challenges.

[ Use Turnstile Analytics ](https://developers.cloudflare.com/turnstile/turnstile-analytics/) 

###  Pre-clearance 

Integrate Cloudflare challenges on single-page applications (SPAs) by allowing Turnstile to issue a Pre-Clearance cookie.

[ Use Pre-clearance ](https://developers.cloudflare.com/cloudflare-challenges/concepts/clearance/#pre-clearance-support-in-turnstile) 

---

## Related products

**[Bots](https://developers.cloudflare.com/bots/)** 

Cloudflare bot solutions identify and mitigate automated traffic to protect your domain from bad bots.

**[DDoS Protection](https://developers.cloudflare.com/ddos-protection/)** 

Detect and mitigate Distributed Denial of Service (DDoS) attacks using Cloudflare's Autonomous Edge.

**[WAF](https://developers.cloudflare.com/waf/)** 

Get automatic protection from vulnerabilities and the flexibility to create custom rules.

---

## More resources

[Plans](https://developers.cloudflare.com/turnstile/plans/) 

Learn more about Turnstile's plan availability.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}}]}
```

---

---
title: Plans
description: Compare Turnstile feature availability and widget limits across plans.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Plans

Cloudflare Turnstile is available on the following plans:

Free plan

The Free plan is best for:

* Personal websites and blogs
* Small to medium businesses
* Development and testing environments
* Most production applications

Enterprise plan

The Enterprise plan is best for:

* Large enterprises with high-volume traffic
* Organizations requiring advanced bot detection and device fingerprinting
* Organizations requiring custom branding, companies with strict compliance requirements
* Multi-domain or complex hosting environments

| Free                                                    | Enterprise              |                                     |
| ------------------------------------------------------- | ----------------------- | ----------------------------------- |
| Pricing                                                 | Free                    | Contact Sales                       |
| Number of widgets                                       | Up to 20 widgets        | Unlimited                           |
| All widget types                                        | Yes                     | Yes                                 |
| Unlimited challenges (traffic or verification requests) | Yes                     | Yes                                 |
| Hostname management                                     | 10 hostnames per widget | Maximum of 200 hostnames per widget |
| Any hostname widget (no preconfigured hostnames)        | No                      | Yes                                 |
| Analytics lookback                                      | 7 days maximum          | 30 days maximum                     |
| Pre-clearance support                                   | Yes                     | Yes                                 |
| Ephemeral IDs                                           | No                      | Yes                                 |
| Offlabel (remove Cloudflare branding)                   | No                      | Yes                                 |
| WCAG 2.2 AAA compliance                                 | Yes                     | Yes                                 |
| Community support                                       | Yes                     | Yes                                 |

Notes

* If you upgrade from Free to Enterprise, your existing widgets and configurations will be preserved during the upgrade process.
* Free users are limited to 20 widgets per account. Customers with Enterprise Bot Management and Enterprise Turnstile can have this limit increased. Contact your account team to discuss your requirements.
* Turnstile can be used independently without requiring other Cloudflare services.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/plans/","name":"Plans"}}]}
```

---

---
title: Turnstile Spin (beta)
description: Set up Turnstile end-to-end (widget + backend siteverify) using an AI coding agent.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Turnstile Spin (beta)

**Last reviewed:**  2 days ago 

Turnstile Spin is a one-shot setup flow for Cloudflare Turnstile. You invoke it through an AI coding agent in your project. The flow lands you with a working widget, a managed siteverify Worker deployed into your Cloudflare account, and a real validation pass against the deployed Worker before you ship.

This page is the canonical Spin skill. It is human-readable and agent-readable. When an agent is told to "follow [developers.cloudflare.com/turnstile/spin ↗](https://developers.cloudflare.com/turnstile/spin)", this is the document it loads.

## Quick start (humans)

If you already have an AI coding agent in your project (Claude Code, Cursor, Codex, OpenCode, GitHub Copilot Chat), paste this prompt into it:

Spin prompt

```

Set up Cloudflare Turnstile in this project end to end. Plan insertion points, create the widget, deploy the managed backend Worker, write the frontend code, and validate the integration.


The full Turnstile Spin skill is inlined below so you can start immediately without fetching anything. Reference URL (only fetch if you need an updated copy): https://developers.cloudflare.com/turnstile/spin/


---


---

name: turnstile-spin

description: Set up Cloudflare Turnstile end-to-end in a project: scan the codebase, create the widget via the Cloudflare API, deploy the managed siteverify Worker, write the frontend snippets, validate, and persist the skill. Load this when a user asks to add Turnstile, set up CAPTCHA, protect a form from bots, or fix a Turnstile integration. Mirrors developers.cloudflare.com/turnstile/spin.

references:

  - vanilla-html

  - nextjs-app

  - nextjs-pages

  - astro

  - sveltekit

  - hugo

---


# Turnstile Spin skill


Turns the prompt "set up Turnstile" into a working end-to-end integration: a widget, a deployed managed siteverify Worker, frontend snippets at every chosen insertion point, and a real validation pass before reporting success.


You are the agent. Run the wizard below by invoking the scripts under `scripts/` and branching on their JSON output. The scripts hold the deterministic logic (API calls, retry/error handling); your job is orchestration, codebase reading, confirmation, and the frontend edits.


Canonical instructions live at [`developers.cloudflare.com/turnstile/spin`](https://developers.cloudflare.com/turnstile/spin/). If the docs page and this file disagree, trust the docs page.


## When to load this skill


Load when the user's prompt mentions any of:


- "Turnstile", "CAPTCHA", "bot protection"

- "siteverify", "cf-turnstile-response"

- "protect this form", "stop bot signups", "spam signups"

- A specific signup, login, or contact form combined with "Cloudflare" or "bot"


Do not load for unrelated Cloudflare tasks (Workers, Pages, R2, etc.) unless Turnstile is also mentioned.


## Conversation flow


The user pasted the prompt. You are in a multi-step dialog. Detect what you can, ask only when you have to, confirm before every irreversible step. Each numbered moment is one agent message. Items marked **[wait for user]** require a user response.


1. **Brief acknowledge.** One sentence: "I'll run Turnstile setup end to end. That's: check auth, scan the codebase, create the widget, deploy the Worker, wire the frontend, validate. Proceed?" **[wait for user]** Do NOT present a plan yet. Auth + scan come first.


2. **Wrangler check.** `npx wrangler --version`. If missing, ask once: "Install wrangler with `npm install --save-dev wrangler` (Node project) or `npm install -g wrangler` (other)? Proceed?" **[wait for user]** If install is blocked entirely (corporate policy, blocked npm), fall back to driving Steps 4-5 via `curl` against `api.cloudflare.com/client/v4/`.


3. **Auth + scope probe (FIRST irreversible action).** Run `scripts/auth-probe.sh`. Branch on `status`:

   - `ok`: continue to Step 4. The script already picked the account (single-account token, or one matching `$CLOUDFLARE_ACCOUNT_ID`).

   - `missing_token`, `missing_scope`, or `missing_workers_scope`: ask the user to create a token at https://dash.cloudflare.com/profile/api-tokens → Custom token → permissions `Account.Turnstile:Edit` **and** `Account.Workers Scripts:Edit` → include the target account in Account Resources. **Do NOT direct them to `wrangler login`**. Its OAuth scope doesn't include `Account.Turnstile:Edit` or `Account.Workers Scripts:Edit`. Offer three ways to hand the token over, cleanest first:

     1. **Export + relaunch** (token never enters chat): `export CLOUDFLARE_API_TOKEN=<token>` then restart the agent from that terminal.

     2. **Save to file** (token in file with user-only perms, not in chat): `umask 077 && printf '%s' '<token>' > ~/.cf-turnstile-token`, then read with `TOKEN=$(cat ~/.cf-turnstile-token)`.

     3. **Paste in chat** (fastest, but token lands in conversation log; user should rotate it after if the log is ever shared).

     If the user picks option 3 (paste in chat), you can use the wait to run Steps 5, 6, 7 (Domain, Codebase scan, Insertion plan). Options 1 and 2 will restart your session, so do not pre-fetch state in those cases. When auth is established, re-run `auth-probe.sh`, then continue to Step 8.

   - `multiple_accounts`: the token covers more than one account and `$CLOUDFLARE_ACCOUNT_ID` is unset. Present the numbered `accounts` list. **[wait for user]** Then export `CLOUDFLARE_ACCOUNT_ID=<chosen>` and re-run `auth-probe.sh`.

   - `account_mismatch`: `$CLOUDFLARE_ACCOUNT_ID` is set but isn't one of the token's accounts. Show the `accounts` list and ask the user to either `unset CLOUDFLARE_ACCOUNT_ID` or set it to one of those IDs.


4. **Account selection.** If `auth-probe.sh` returned `ok` after a `multiple_accounts` round-trip, this is already done. Otherwise the script picked the single account silently and you continue to Step 5.


5. **Domain.** Always include `localhost` and `127.0.0.1`. For production, scan `package.json` `homepage`, `wrangler.toml`, `README.md`, `AGENTS.md`, git remote. Confirm: "I'll register for `localhost`, `127.0.0.1`, and `<domain>`. OK?" **[wait for user]** If no production domain is found, ask.


6. **Codebase scan.** Detect framework + insertion candidates silently.


7. **Insertion plan.** Show the candidate list with `[recommended]` / `[skip by default]` markers; ask the user to confirm (numbers, "all", "recommended", or a list). **[wait for user]** If an existing CAPTCHA was detected, present a migration plan instead (see "Migrating from another CAPTCHA").


8. **Widget creation.** Run `scripts/widget-create.sh --account-id <id> --name <name> --domains <list> --mode managed`. Report the sitekey. The secret stays in env; never write it to disk.


9. **Worker deploy.** Run `scripts/worker-deploy.sh --name turnstile-siteverify-<project-slug>` with `WIDGET_SECRET` exported. Report the Worker URL on `status: ok`. On `set_secret_failed`, the Worker deployed but `TURNSTILE_SECRET_KEY` is not set on it; surface the error, then retry with `echo "$WIDGET_SECRET" | npx wrangler secret put TURNSTILE_SECRET_KEY --name <returned worker_name>` before running validation.


10. **Frontend edits.** State the contract: "I'll add the widget + gate the existing submit handler on `success === true`. The existing handler logic stays the same." Ask "yes" / "show". **[wait for user]** If "show", print unified diffs and ask again. Do NOT propose alternate behavior (mail delivery, custom backends).


11. **Validation.** Run `scripts/validate.sh`. Report each check as it passes. If any fails, surface the error and stop. **[wait for user if anything fails]**


12. **Persist skill.** Ask: "Save the Spin skill to `.claude/skills/turnstile-spin/SKILL.md` so I can reuse it on follow-up tasks?" Default yes. **[wait for user]** Then run `scripts/persist-skill.sh --path <agent-specific-path>`.


13. **Final report.** Print the structured summary: what was created, what was validated, what to do next.


### Things you must NOT do


- Do not write the Turnstile secret to disk. Only pass it via stdin to `wrangler secret put` (the worker-deploy.sh script handles this).

- Do not skip validation.

- Do not overwrite files without showing a diff.

- Do not deploy a Worker to a different account than the widget was created in.

- Do not call siteverify from the browser. Always: browser → user's Worker → siteverify.

- Do not use `sudo` or install global packages without asking.


### Hard scope boundary: DO NOT ask the user about


Spin validates the Turnstile token via a managed Worker before the user's existing form handler runs. Everything else is out of scope:


- **Email / SMS / notification delivery.** Leave the existing submit handler alone (just gate it on `success === true`). Don't propose Resend, Mailchannels, SMTP, mailto.

- **Custom Worker code.** Deploy the stock Worker template bundled at `templates/worker/`. Don't write a new Worker. Don't add features (rate limiting, custom routing, third-party integrations).

- **Database / payment / OAuth / form persistence.** Out of scope.

- **Frontend framework migration, refactoring, or styling.** Edit only what's needed.

- **reCAPTCHA v3 score thresholds.** Turnstile returns `success: true/false`.

- **Pre-clearance-only setups.** If `clearance_level !== no_clearance`, siteverify is optional and Spin doesn't apply. Redirect the user and exit.


### Recovery flow: respect existing widget configuration


If the user tells you they already have a Turnstile widget set up and want to wire siteverify to it without rotating the sitekey (e.g. "I have a sitekey but siteverify never worked", "set up Spin against my existing widget `<sitekey>`"):


1. Skip Step 8 (widget creation). The sitekey already exists; get it from the user.

2. Fetch the widget metadata via `scripts/fetch-secret.sh --account-id <id> --sitekey <key>`. Branch on `status`:

   - `ok`: read `secret`, `clearance_level`, and `domains` from the response. Confirm `domains` includes the user's production hostname; if not, surface the gap before proceeding.

   - `missing_read_scope`: tell the user to add `Account.Turnstile:Read` to the token, or fall back to asking them to paste the secret. In the paste path, you do not have `clearance_level` or `domains`; ask the user to confirm both.

3. Check `clearance_level` from the response (or the user's answer):

   - `no_clearance`: standard recovery (deploy Worker, wire siteverify).

   - anything else: ask whether they want siteverify on top of pre-clearance, or exit per the scope boundary.

4. Continue from Step 9 (Worker deploy). Site key does not change. Dashboard's `Deployment` column flips from `Manual` to `Spin` on the first request carrying `data-action="turnstile-spin-v1"`.

5. Never recreate the widget to get a fresh secret. That breaks the existing sitekey everywhere it's deployed.


### The frontend-edit contract


When wiring an existing form to the Worker (Step 10), the contract is: **gate, don't replace.** The user's existing submit handler keeps doing what it did. Spin only adds a validation step before it.


```js

form.addEventListener("submit", async (e) => {

  e.preventDefault();

  const token = /* read cf-turnstile-response */;

  const result = await fetch(WORKER_URL, { method: 'POST', body: JSON.stringify({ token }) });

  const data = await result.json();

  if (!data.success) return; // show failure

  // existing handler logic runs here, unchanged

});

```


If the existing handler was a stub, Spin leaves it a stub gated on success. The user can replace the stub later; that's not Spin's job.


## Migrating from another CAPTCHA


During the Step 6 codebase scan, also look for existing reCAPTCHA or hCaptcha. If found, switch Step 7 to a migration plan.


Detection signals:

- reCAPTCHA: `https://www.google.com/recaptcha/api.js`, `class="g-recaptcha"`, `data-sitekey="6L..."`, backend POST to `/recaptcha/api/siteverify`

- hCaptcha: `https://js.hcaptcha.com/1/api.js`, `class="h-captcha"`, backend POST to `https://hcaptcha.com/siteverify`


Substitution:

- Replace script tags with `https://challenges.cloudflare.com/turnstile/v0/api.js` (`async defer`).

- Replace `class="g-recaptcha"` / `class="h-captcha"` divs with `class="cf-turnstile"`, update `data-sitekey` to the new Turnstile sitekey, add `data-action="turnstile-spin-v1"`.

- **Remove** any manually-added `<input type="hidden" name="g-recaptcha-response">` or `name="h-captcha-response"` elements. Turnstile renders its own hidden input named `cf-turnstile-response` automatically when it parses the `cf-turnstile` div — do not rename the old field, delete it.

- Backend siteverify URL points at the Spin-deployed Worker. Drop `RECAPTCHA_SECRET` / `HCAPTCHA_SECRET` env vars (the Worker holds the secret).

- The Spin Worker accepts `{ token }`, `{ "cf-turnstile-response": ... }`, **or** `{ response }` in JSON or form-encoded bodies. Backends migrated from reCAPTCHA/hCaptcha can keep sending `{ secret, response, remoteip }` minus the `secret` field — `response` is preserved for drop-in migration. Response shape is identical (`success`, `error-codes`).


Edge cases to surface to the user:

- **reCAPTCHA v3 score thresholds.** Turnstile has no score. Tell the user explicitly that migrated code will reject on `success === false`.

- **reCAPTCHA Enterprise.** Don't auto-migrate. Point at [developers.cloudflare.com/turnstile/migration/recaptcha/](https://developers.cloudflare.com/turnstile/migration/recaptcha/).

- **Custom `action=` values.** Preserve any custom action the user passed to `grecaptcha.execute` as `data-action` on the widget. Use `turnstile-spin-v1` only when no custom action exists.


## Edge cases


| Situation | Action |

|---|---|

| `wrangler` not installed | Install path: `npm install --save-dev wrangler` (Node project) or `npm install -g wrangler` (other) |

| Multiple Cloudflare accounts | `scripts/auth-probe.sh` returns all accounts; ask the user to choose, export `CLOUDFLARE_ACCOUNT_ID` |

| Cloudflare Pages project | Deploy the managed Worker anyway, OR suggest the [Pages Plugin](https://developers.cloudflare.com/pages/functions/plugins/turnstile/) |

| `EXPECTED_HOSTNAME` mismatch | Update widget domains via PUT, not PATCH (PATCH returns `10405 Method not allowed`): `curl -X PUT .../widgets/$SITEKEY -d '{"name":"...","mode":"managed","domains":[...]}'` |

| Worker name conflict | `worker-deploy.sh` retries automatically with a hash suffix |

| Token expired mid-flow | Stop, re-run `scripts/auth-probe.sh`, prompt for fresh credentials |

| Step 11 returns `missing-input-secret` | Secret didn't propagate. Re-set: `echo "$WIDGET_SECRET" \| npx wrangler secret put TURNSTILE_SECRET_KEY --name <worker_name from worker-deploy.sh output>`, wait 10s, re-validate. Use the `worker_name` field returned by `worker-deploy.sh`; do not rely on a `$WORKER_NAME` env var. |

| `worker-deploy.sh` returns `set_secret_failed` | Worker is deployed but secret is not set. Re-run only the secret-put using the returned `worker_name`: `echo "$WIDGET_SECRET" \| npx wrangler secret put TURNSTILE_SECRET_KEY --name <worker_name>`. Surface the `detail` field to the user — it carries the wrangler error. |


## Telemetry marker


Every snippet you write must include `data-action="turnstile-spin-v1"`. Account-level aggregate telemetry, never per-user. Cloudflare uses it to measure activation. If the user removes the attribute, the integration still works; only the analytics segmentation is lost.


## Do not


- Do not write the secret to disk.

- Do not skip validation (Step 11).

- Do not propose features outside the wizard (custom Worker code, custom domains, advanced WAF rules) unless asked.

- Do not call siteverify from the browser.

- Do not deploy the Worker into a different account than the widget.


---


## Helper scripts (bootstrap before the wizard)


The wizard above references deterministic helper scripts. Write these files under `/tmp/turnstile-spin-scripts/` before starting, then `export TURNSTILE_SPIN_SCRIPTS=/tmp/turnstile-spin-scripts` and `chmod +x /tmp/turnstile-spin-scripts/*.sh`.


*If you have the `cloudflare/skills` bundle installed locally, skip this section. The scripts ship alongside the SKILL.md you are reading; this bootstrap is for the ad-hoc paste-into-agent case.*


### `/tmp/turnstile-spin-scripts/auth-probe.sh`


```sh

#!/usr/bin/env bash

# Probes Cloudflare API auth state for the Turnstile Spin agent.

#

# Reads:

#   $CLOUDFLARE_API_TOKEN  (required)

#   $CLOUDFLARE_ACCOUNT_ID (optional; if set, must be one of the token's accounts)

#

# Outputs JSON to stdout, always exits 0. The agent reads `status`:

#   "ok"                   ; selected account passed both Turnstile and Workers scope probes

#   "missing_token"        ; no token set, or wrangler whoami failed

#   "missing_scope"        ; token lacks Account.Turnstile:Edit on the selected account

#   "missing_workers_scope"; token has Turnstile scope but lacks Workers Scripts on the selected account

#   "multiple_accounts"    ; token covers >1 accounts and $CLOUDFLARE_ACCOUNT_ID is unset; agent must ask user to pick, set it, and re-run

#   "account_mismatch"     ; $CLOUDFLARE_ACCOUNT_ID is set but is not in the token's accounts list

#

# Human-readable diagnostics go to stderr. The agent surfaces them to the user.


set -uo pipefail


emit() {

  echo "$1"

  exit 0

}


token="${CLOUDFLARE_API_TOKEN:-}"

declared_account="${CLOUDFLARE_ACCOUNT_ID:-}"


if [ -z "$token" ]; then

  echo "auth-probe: \$CLOUDFLARE_API_TOKEN is not set." >&2

  emit '{"status":"missing_token","reason":"no_env_var"}'

fi


whoami_json=$(npx wrangler whoami --json 2>/dev/null || true)

if [ -z "$whoami_json" ] || [ "$(echo "$whoami_json" | head -c 1)" != "{" ]; then

  echo "auth-probe: wrangler whoami returned no JSON. Token may be invalid or expired." >&2

  emit '{"status":"missing_token","reason":"whoami_failed"}'

fi


# Extract the accounts array. Fall back to python3 if jq is missing.

accounts_json=$(echo "$whoami_json" | (jq -c '.accounts' 2>/dev/null || python3 -c "import sys,json; print(json.dumps(json.load(sys.stdin)['accounts']))"))

account_count=$(echo "$accounts_json" | (jq 'length' 2>/dev/null || python3 -c "import sys,json; print(len(json.load(sys.stdin)))"))


if [ -z "$account_count" ] || [ "$account_count" = "0" ] || [ "$account_count" = "null" ]; then

  echo "auth-probe: wrangler whoami succeeded but no accounts found on the token." >&2

  emit '{"status":"missing_token","reason":"no_accounts"}'

fi


# Pick the account to probe:

#   - $CLOUDFLARE_ACCOUNT_ID set: must be in the token's accounts list, else account_mismatch

#   - unset, exactly 1 account: use it silently

#   - unset, >1 accounts: emit multiple_accounts; agent picks and re-runs

if [ -n "$declared_account" ]; then

  in_list=$(echo "$accounts_json" | (jq --arg id "$declared_account" 'map(.id) | index($id) != null' 2>/dev/null || python3 -c "import sys,json; print('true' if any(a['id']==sys.argv[1] for a in json.load(sys.stdin)) else 'false')" "$declared_account"))

  if [ "$in_list" != "true" ]; then

    echo "auth-probe: \$CLOUDFLARE_ACCOUNT_ID ($declared_account) is not one of the token's accounts." >&2

    echo "auth-probe: Either unset \$CLOUDFLARE_ACCOUNT_ID, or set it to an account included in the token's Account Resources." >&2

    emit "{\"status\":\"account_mismatch\",\"declared\":\"$declared_account\",\"accounts\":$accounts_json}"

  fi

  account_id="$declared_account"

elif [ "$account_count" = "1" ]; then

  account_id=$(echo "$accounts_json" | (jq -r '.[0].id' 2>/dev/null || python3 -c "import sys,json; print(json.load(sys.stdin)[0]['id'])"))

else

  echo "auth-probe: token covers $account_count accounts; ask the user to pick one, then export \$CLOUDFLARE_ACCOUNT_ID and re-run." >&2

  emit "{\"status\":\"multiple_accounts\",\"accounts\":$accounts_json}"

fi


# Probe Turnstile scope on the selected account

tmp=$(mktemp)

http_code=$(curl -sS -w "%{http_code}" -o "$tmp" \

  "https://api.cloudflare.com/client/v4/accounts/$account_id/challenges/widgets" \

  -H "Authorization: Bearer $token" 2>/dev/null || echo "000")

body=$(cat "$tmp"); rm -f "$tmp"

success=$(echo "$body" | (jq -r '.success' 2>/dev/null || echo "false"))


if [ "$success" != "true" ]; then

  echo "auth-probe: token cannot read /challenges/widgets on account $account_id (HTTP $http_code). Missing Account.Turnstile:Edit." >&2

  emit "{\"status\":\"missing_scope\",\"account_id\":\"$account_id\",\"http_code\":$http_code}"

fi


# Probe Workers scope on the selected account. GET /workers/scripts requires

# Account.Workers Scripts:Read, which is a best-effort proxy for Edit. Tokens

# granted Edit-only (without Read) will fail this probe and emit a confusing

# missing_workers_scope; the agent should suggest adding Read alongside Edit.

tmp=$(mktemp)

workers_code=$(curl -sS -w "%{http_code}" -o "$tmp" \

  "https://api.cloudflare.com/client/v4/accounts/$account_id/workers/scripts" \

  -H "Authorization: Bearer $token" 2>/dev/null || echo "000")

workers_body=$(cat "$tmp"); rm -f "$tmp"

workers_success=$(echo "$workers_body" | (jq -r '.success' 2>/dev/null || echo "false"))


if [ "$workers_success" != "true" ]; then

  echo "auth-probe: token cannot read /workers/scripts on account $account_id (HTTP $workers_code). Missing Account.Workers Scripts:Edit." >&2

  emit "{\"status\":\"missing_workers_scope\",\"account_id\":\"$account_id\",\"http_code\":$workers_code}"

fi


emit "{\"status\":\"ok\",\"account_id\":\"$account_id\",\"accounts\":$accounts_json}"

```


### `/tmp/turnstile-spin-scripts/fetch-secret.sh`


```sh

#!/usr/bin/env bash

# Retrieves the secret for an existing Turnstile widget via the Cloudflare API.

# Used by the recovery flow when binding the secret to a freshly deployed Worker.

#

# Reads:

#   $CLOUDFLARE_API_TOKEN (required)

#

# Args:

#   --account-id <id>   Cloudflare account ID

#   --sitekey <key>     Widget sitekey to look up

#

# Outputs JSON. Exit 0 on success, 1 on failure.

#   ok:        {"status":"ok","secret":"<secret>","clearance_level":"<level>","domains":[<list>]}

#   no_scope:  {"status":"missing_read_scope","detail":"token lacks Account.Turnstile:Read"}

#   not_found: {"status":"error","reason":"widget_not_found","http_code":<code>}

#

# The agent uses clearance_level to enforce the pre-clearance scope boundary

# (Spin only applies to widgets where clearance_level == "no_clearance"; for

# other levels siteverify is optional and the recovery flow should exit).

#

# Never propose recreating the widget to get a fresh secret; that breaks

# the existing sitekey everywhere the user has it deployed in their frontend.


set -uo pipefail


while [[ $# -gt 0 ]]; do

  case $1 in

    --account-id) ACCOUNT_ID="$2"; shift 2 ;;

    --sitekey)    SITEKEY="$2"; shift 2 ;;

    *) echo "fetch-secret: unknown arg $1" >&2; exit 2 ;;

  esac

done


: "${CLOUDFLARE_API_TOKEN:?CLOUDFLARE_API_TOKEN must be set}"

: "${ACCOUNT_ID:?--account-id required}"

: "${SITEKEY:?--sitekey required}"


tmp=$(mktemp)

http_code=$(curl -sS -w "%{http_code}" -o "$tmp" \

  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/challenges/widgets/$SITEKEY" \

  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" 2>/dev/null || echo "000")

body=$(cat "$tmp"); rm -f "$tmp"


if [ "$http_code" = "200" ]; then

  secret=$(echo "$body" | (jq -r '.result.secret' 2>/dev/null || python3 -c "import sys,json; print(json.load(sys.stdin)['result']['secret'])"))

  clearance=$(echo "$body" | (jq -r '.result.clearance_level // "no_clearance"' 2>/dev/null || python3 -c "import sys,json; print(json.load(sys.stdin)['result'].get('clearance_level','no_clearance'))"))

  domains=$(echo "$body" | (jq -c '.result.domains // []' 2>/dev/null || python3 -c "import sys,json; print(json.dumps(json.load(sys.stdin)['result'].get('domains',[])))"))

  if [ -n "$secret" ] && [ "$secret" != "null" ]; then

    echo "{\"status\":\"ok\",\"secret\":\"$secret\",\"clearance_level\":\"$clearance\",\"domains\":$domains}"

    exit 0

  fi

fi


if [ "$http_code" = "403" ]; then

  code=$(echo "$body" | (jq -r '.errors[0].code // 0' 2>/dev/null || echo "0"))

  if [ "$code" = "10000" ]; then

    echo "fetch-secret: token can edit Turnstile widgets but cannot read this one's secret." >&2

    echo "fetch-secret: add Account.Turnstile:Read to the token, or fall back to user paste." >&2

    echo "{\"status\":\"missing_read_scope\",\"detail\":\"token lacks Account.Turnstile:Read\"}"

    exit 1

  fi

fi


echo "fetch-secret: widget lookup failed (HTTP $http_code)." >&2

echo "{\"status\":\"error\",\"reason\":\"widget_not_found\",\"http_code\":$http_code}"

exit 1

```


### `/tmp/turnstile-spin-scripts/persist-skill.sh`


```sh

#!/usr/bin/env bash

# Persists the canonical Spin skill bundle (SKILL.md + scripts/ + references/)

# from cloudflare/skills to the user's repo so the agent can re-load it on

# follow-up tasks without re-pasting the bootstrap prompt.

#

# Args:

#   --path <path>   SKILL.md destination, e.g. .claude/skills/turnstile-spin/SKILL.md.

#                   The bundle is extracted into the parent directory of <path>,

#                   so scripts land at e.g. .claude/skills/turnstile-spin/scripts/.

#

# Outputs JSON. Exit 0 if the bundle was written, 1 on failure.

#   ok:    {"status":"ok","path":"<path>","bundle_root":"<dir>","scripts":[<list>]}

#   fail:  {"status":"error","reason":"<reason>"}


set -uo pipefail


PATH_ARG=""

while [[ $# -gt 0 ]]; do

  case $1 in

    --path) PATH_ARG="$2"; shift 2 ;;

    *) echo "persist-skill: unknown arg $1" >&2; exit 2 ;;

  esac

done


: "${PATH_ARG:?--path required}"


TARGET_DIR=$(dirname "$PATH_ARG")

mkdir -p "$TARGET_DIR"


# Install the canonical bundle from cloudflare/skills via degit. This writes

# SKILL.md, scripts/, references/, templates/, tests/ into $TARGET_DIR.

if ! npx --yes degit cloudflare/skills/skills/turnstile-spin "$TARGET_DIR" >/dev/null 2>&1; then

  echo "persist-skill: degit failed; cannot fetch cloudflare/skills/skills/turnstile-spin." >&2

  echo "persist-skill: ensure your network can reach github.com and try again, or install manually." >&2

  echo "{\"status\":\"error\",\"reason\":\"degit_failed\"}"

  exit 1

fi


if [ ! -f "$TARGET_DIR/SKILL.md" ]; then

  echo "persist-skill: bundle extracted but SKILL.md is missing at $TARGET_DIR/SKILL.md." >&2

  echo "{\"status\":\"error\",\"reason\":\"skill_missing\"}"

  exit 1

fi


# Make scripts executable so the agent can invoke them directly.

if [ -d "$TARGET_DIR/scripts" ]; then

  chmod +x "$TARGET_DIR/scripts"/*.sh 2>/dev/null || true

fi


scripts_list=$(ls "$TARGET_DIR/scripts" 2>/dev/null | sed 's/.*/"&"/' | paste -sd, -)

echo "persist-skill: wrote bundle to $TARGET_DIR" >&2

echo "{\"status\":\"ok\",\"path\":\"$PATH_ARG\",\"bundle_root\":\"$TARGET_DIR\",\"scripts\":[$scripts_list]}"

exit 0

```


### `/tmp/turnstile-spin-scripts/validate.sh`


```sh

#!/usr/bin/env bash

# Validates a deployed Turnstile siteverify Worker end-to-end.

#

# Reads:

#   $CLOUDFLARE_API_TOKEN (required for hostname check)

#

# Args:

#   --worker-url <url>     Deployed Worker URL (from worker-deploy.sh)

#   --account-id <id>      Cloudflare account ID

#   --sitekey <key>        Widget sitekey (from widget-create.sh)

#   --expected-domains <a,b,c>  Comma-separated domains that must appear in the widget's domains array

#

# Outputs JSON. Exit 0 if all three checks pass, 1 otherwise.

#   ok:    {"status":"ok"}

#   fail:  {"status":"error","check":"health|dummy_siteverify|worker_metadata|hostname","detail":"<msg>"}


set -uo pipefail


while [[ $# -gt 0 ]]; do

  case $1 in

    --worker-url)       WORKER_URL="$2"; shift 2 ;;

    --account-id)       ACCOUNT_ID="$2"; shift 2 ;;

    --sitekey)          SITEKEY="$2"; shift 2 ;;

    --expected-domains) EXPECTED_DOMAINS="$2"; shift 2 ;;

    *) echo "validate: unknown arg $1" >&2; exit 2 ;;

  esac

done


: "${CLOUDFLARE_API_TOKEN:?CLOUDFLARE_API_TOKEN must be set}"

: "${WORKER_URL:?--worker-url required}"

: "${ACCOUNT_ID:?--account-id required}"

: "${SITEKEY:?--sitekey required}"

: "${EXPECTED_DOMAINS:?--expected-domains required}"


# Check 1: health endpoint

health=$(curl -sSf "${WORKER_URL}/health" 2>/dev/null || echo "")

if [ -z "$health" ] || ! echo "$health" | grep -q '"ok":true'; then

  echo "validate: health check failed; $WORKER_URL/health did not return {ok:true,version:...}" >&2

  echo "{\"status\":\"error\",\"check\":\"health\",\"detail\":\"worker /health did not respond ok:true\"}"

  exit 1

fi


# Check 2: dummy siteverify; should return success:false + error-codes array

dummy=$(curl -sS -X POST "${WORKER_URL}/" \

  -H "Content-Type: application/json" \

  -d '{"token":"XXXX.DUMMY.TOKEN.XXXX"}' 2>/dev/null || echo "")


success=$(echo "$dummy" | (jq -r '.success // "missing"' 2>/dev/null || echo "missing"))

errors=$(echo "$dummy" | (jq -r '.["error-codes"] | length // 0' 2>/dev/null || echo "0"))


if [ "$success" != "false" ] || [ "$errors" = "0" ]; then

  echo "validate: dummy siteverify check failed; expected success:false + error-codes; got: $dummy" >&2

  echo "{\"status\":\"error\",\"check\":\"dummy_siteverify\",\"detail\":\"unexpected response shape\"}"

  exit 1

fi


# Check 2b: confirm the Worker is the managed template (not a customer-written

# replacement) by looking for the _worker metadata field. If absent, the user

# deployed a custom Worker; surface it so the agent can alert them.

worker_meta=$(echo "$dummy" | (jq -r '._worker.worker_version // "missing"' 2>/dev/null || echo "missing"))

if [ "$worker_meta" = "missing" ]; then

  echo "validate: _worker metadata missing from response; this is not the managed Spin Worker template." >&2

  echo "{\"status\":\"error\",\"check\":\"worker_metadata\",\"detail\":\"_worker field missing; user may have deployed a custom Worker\"}"

  exit 1

fi


# Check 3: hostname / widget domains registered

widget=$(curl -sS \

  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/challenges/widgets/$SITEKEY" \

  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" 2>/dev/null)

registered=$(echo "$widget" | (jq -r '.result.domains[]' 2>/dev/null || python3 -c "import sys,json; [print(d) for d in json.load(sys.stdin)['result']['domains']]"))


missing=""

IFS=',' read -ra DOMS <<< "$EXPECTED_DOMAINS"

for d in "${DOMS[@]}"; do

  if ! echo "$registered" | grep -qFx "$d"; then

    missing="${missing}${d} "

  fi

done


if [ -n "$missing" ]; then

  echo "validate: hostname check failed; domains not on widget: $missing" >&2

  echo "{\"status\":\"error\",\"check\":\"hostname\",\"detail\":\"missing domains: ${missing% }\"}"

  exit 1

fi


echo '{"status":"ok"}'

```


### `/tmp/turnstile-spin-scripts/widget-create.sh`


```sh

#!/usr/bin/env bash

# Creates a Turnstile widget via the Cloudflare API.

#

# Reads:

#   $CLOUDFLARE_API_TOKEN (required)

#

# Args:

#   --account-id <id>        Cloudflare account ID

#   --name <name>            Widget name (e.g. "myproject (Spin)")

#   --domains <a,b,c>        Comma-separated domain list (include localhost,127.0.0.1)

#   --mode <managed|invisible|non-interactive>  Default: managed

#

# Outputs JSON to stdout. Exit 0 on success, 1 on failure. Diagnostics on stderr.

#   ok:    {"status":"ok","sitekey":"<key>","secret":"<secret>"}

#   error: {"status":"error","code":<code>,"message":"<msg>"}

#     code 10000 → token lacks Account.Turnstile:Edit


set -uo pipefail


MODE="managed"

while [[ $# -gt 0 ]]; do

  case $1 in

    --account-id) ACCOUNT_ID="$2"; shift 2 ;;

    --name)       NAME="$2"; shift 2 ;;

    --domains)    DOMAINS="$2"; shift 2 ;;

    --mode)       MODE="$2"; shift 2 ;;

    *) echo "widget-create: unknown arg $1" >&2; exit 2 ;;

  esac

done


: "${CLOUDFLARE_API_TOKEN:?CLOUDFLARE_API_TOKEN must be set}"

: "${ACCOUNT_ID:?--account-id required}"

: "${NAME:?--name required}"

: "${DOMAINS:?--domains required}"


domains_json=$(python3 -c "import sys; print(__import__('json').dumps(sys.argv[1].split(',')))" "$DOMAINS")


body=$(curl -sS -X POST \

  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/challenges/widgets" \

  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  -H "Content-Type: application/json" \

  -d "{\"name\":\"$NAME\",\"domains\":$domains_json,\"mode\":\"$MODE\"}" 2>/dev/null)


success=$(echo "$body" | (jq -r '.success' 2>/dev/null || python3 -c "import sys,json; print(str(json.load(sys.stdin).get('success',False)).lower())"))


if [ "$success" = "true" ]; then

  sitekey=$(echo "$body" | (jq -r '.result.sitekey' 2>/dev/null || python3 -c "import sys,json; print(json.load(sys.stdin)['result']['sitekey'])"))

  secret=$(echo "$body" | (jq -r '.result.secret' 2>/dev/null || python3 -c "import sys,json; print(json.load(sys.stdin)['result']['secret'])"))

  echo "{\"status\":\"ok\",\"sitekey\":\"$sitekey\",\"secret\":\"$secret\"}"

  exit 0

fi


code=$(echo "$body" | (jq -r '.errors[0].code // 0' 2>/dev/null || echo "0"))

message=$(echo "$body" | (jq -r '.errors[0].message // "unknown"' 2>/dev/null || echo "unknown") | tr -d '"')

echo "widget-create: failed (code=$code): $message" >&2

echo "{\"status\":\"error\",\"code\":$code,\"message\":\"$message\"}"

exit 1

```


### `/tmp/turnstile-spin-scripts/worker-deploy.sh`


```sh

#!/usr/bin/env bash

# Deploys the managed siteverify Worker template to the user's account

# and sets TURNSTILE_SECRET_KEY as a Worker secret.

#

# Reads:

#   $CLOUDFLARE_API_TOKEN (required)

#   $WIDGET_SECRET        (required; secret captured from widget-create.sh)

#

# Args:

#   --name <worker-name>   Base name; appends a hash suffix if taken

#   --deploy-dir <path>    Where to extract the template. Default: /tmp/turnstile-siteverify-deploy

#

# Outputs JSON. Exit 0 on success, non-zero on failure.

#   ok:            {"status":"ok","worker_url":"<url>","worker_name":"<name>"}

#   conflict:      {"status":"error","reason":"name_conflict_after_retry"}

#   deploy_failed: {"status":"error","reason":"deploy_failed"}

#   set_secret:    {"status":"error","reason":"set_secret_failed","worker_name":"<name>"}

#   url_parse:     {"status":"error","reason":"url_parse_failed","worker_name":"<name>"}


set -uo pipefail


NAME="${WORKER_NAME:-turnstile-siteverify}"

DEPLOY_DIR="/tmp/turnstile-siteverify-deploy"

while [[ $# -gt 0 ]]; do

  case $1 in

    --name)       NAME="$2"; shift 2 ;;

    --deploy-dir) DEPLOY_DIR="$2"; shift 2 ;;

    *) echo "worker-deploy: unknown arg $1" >&2; exit 2 ;;

  esac

done


: "${CLOUDFLARE_API_TOKEN:?CLOUDFLARE_API_TOKEN must be set}"

: "${WIDGET_SECRET:?WIDGET_SECRET must be set}"


deploy_log=$(mktemp)


deploy() {

  local target_name="$1"

  rm -rf "$DEPLOY_DIR"

  npx --yes degit cloudflare/skills/skills/turnstile-spin/templates/worker "$DEPLOY_DIR" >/dev/null 2>&1

  # Capture both streams. Wrangler prints the success URL and version ID on

  # stdout; progress indicators on stderr. Capturing only stderr loses the URL.

  (cd "$DEPLOY_DIR" && npx wrangler deploy --name "$target_name") >"$deploy_log" 2>&1

}


if ! deploy "$NAME"; then

  if grep -q "script name already in use" "$deploy_log"; then

    NAME="${NAME}-$(openssl rand -hex 3 2>/dev/null || date +%s | tail -c 5)"

    echo "worker-deploy: name conflict; retrying as $NAME" >&2

    if ! deploy "$NAME"; then

      echo "worker-deploy: deploy failed even with new name" >&2

      cat "$deploy_log" >&2

      rm -f "$deploy_log"

      echo "{\"status\":\"error\",\"reason\":\"name_conflict_after_retry\"}"

      exit 1

    fi

  else

    cat "$deploy_log" >&2

    rm -f "$deploy_log"

    echo "{\"status\":\"error\",\"reason\":\"deploy_failed\"}"

    exit 1

  fi

fi


# Set the secret. Use `echo` (not `printf '%s'`); wrangler secret put expects

# newline-terminated stdin; printf without a trailing newline lands an empty

# secret in the runtime even though wrangler reports success.

secret_log=$(mktemp)

set_secret() {

  echo "$WIDGET_SECRET" | (cd "$DEPLOY_DIR" && npx wrangler secret put TURNSTILE_SECRET_KEY --name "$NAME") >"$secret_log" 2>&1

}


if ! set_secret; then

  echo "worker-deploy: failed to set TURNSTILE_SECRET_KEY on $NAME" >&2

  cat "$secret_log" >&2

  detail=$(tail -3 "$secret_log" | tr '\n' ' ' | sed 's/"/\\"/g' | head -c 200)

  rm -f "$deploy_log" "$secret_log"

  echo "{\"status\":\"error\",\"reason\":\"set_secret_failed\",\"worker_name\":\"$NAME\",\"detail\":\"$detail\"}"

  exit 1

fi

rm -f "$secret_log"

sleep 5


# Extract the deployed URL. Try workers.dev first, then any https URL in the

# log that is not the well-known cloudflare.com host (custom domain deploys

# and Workers for Platforms don't always land at a workers.dev hostname).

worker_url=$(grep -oE 'https://[a-zA-Z0-9._-]+\.workers\.dev' "$deploy_log" | head -1)

if [ -z "$worker_url" ]; then

  worker_url=$(grep -oE 'https://[a-zA-Z0-9.-]+(/[^[:space:]]*)?' "$deploy_log" \

    | grep -v -E 'cloudflare\.com|workers-sdk|github\.com' \

    | head -1)

fi

rm -f "$deploy_log"


if [ -z "$worker_url" ]; then

  echo "worker-deploy: deployed but could not parse Worker URL from wrangler output" >&2

  echo "worker-deploy: ask the user for the URL printed by wrangler deploy and pass it to validate.sh manually" >&2

  echo "{\"status\":\"error\",\"reason\":\"url_parse_failed\",\"worker_name\":\"$NAME\"}"

  exit 1

fi


echo "{\"status\":\"ok\",\"worker_url\":\"$worker_url\",\"worker_name\":\"$NAME\"}"

```


```

If you would rather save the skill locally first so the agent has it on disk:

One-line install per agent

```

# Claude Code

mkdir -p .claude/skills/turnstile-spin && \

  curl -sSL https://developers.cloudflare.com/turnstile/spin/index.md \

  -o .claude/skills/turnstile-spin/SKILL.md


# Cursor

mkdir -p .cursor/rules && \

  curl -sSL https://developers.cloudflare.com/turnstile/spin/index.md \

  -o .cursor/rules/turnstile-spin.md


# OpenCode

mkdir -p .opencode/skills/turnstile-spin && \

  curl -sSL https://developers.cloudflare.com/turnstile/spin/index.md \

  -o .opencode/skills/turnstile-spin/SKILL.md


```

Then prompt your agent: `Use the turnstile-spin skill to add Turnstile to this project.`

## What happens after you paste the prompt

The agent does not run silently. It detects what it can, asks only when it has to, and confirms before every irreversible step. The flow below is the contract the agent follows. Both for humans reading this page to know what to expect, and for agents reading this page as the source of truth.

### 1\. Acknowledge

The agent fetches this page, reads the wizard, and tells you what it's about to do:

> **Agent:** I'll set up Cloudflare Turnstile end to end: check your Cloudflare auth, scan the codebase for forms, create a widget, deploy the managed siteverify Worker, write the frontend snippets, and validate. Proceed?

You can say "yes" or jump in with constraints ("only protect /signup", "use the staging account").

### 2\. Wrangler check

`npx wrangler --version`. If missing:

> **Agent:** Wrangler isn't installed. I can install it locally with `npm install --save-dev wrangler`. Proceed?

For non-Node projects:

> **Agent:** This isn't a Node project. Please run `npm install -g wrangler` (or your package manager's equivalent) and tell me when it's done.

The agent does not run `sudo` and does not install globally without your confirmation.

**Locked-down environment fallback.** If the user can't install wrangler at all (corporate policy, no Node, blocked npm registry), do not dead-end. Switch to the direct-API path: ask the user for a Cloudflare API token with `Account.Turnstile:Edit` and `Workers Scripts:Edit` permissions, then drive Steps 4 and 5 via `curl` against `api.cloudflare.com/client/v4/` instead of `wrangler`. The Worker upload uses the [Workers script upload endpoint](https://developers.cloudflare.com/api/operations/worker-script-upload-worker-module); the widget create uses [POST /accounts/{id}/challenges/widgets](https://developers.cloudflare.com/api/operations/turnstile-widgets-list-turnstile-widgets).

### 3\. Authentication

`npx wrangler whoami`. Two paths.

Already authenticated:

> **Agent:** You're authenticated as `you@example.com` on Acme Corp. Use this account?

Not authenticated, or token missing the required scopes:

> **Agent:** I need a Cloudflare API token with `Account.Turnstile:Edit` and `Account.Workers Scripts:Edit`. Create one at [https://dash.cloudflare.com/profile/api-tokens ↗](https://dash.cloudflare.com/profile/api-tokens) (Custom token), include the target account in Account Resources, then either `export CLOUDFLARE_API_TOKEN=<token>` and re-launch me, or paste it here.

The skill does not use `wrangler login`. OAuth-based wrangler sessions do not include `Account.Turnstile:Edit` or `Account.Workers Scripts:Edit`, so they cannot create widgets or deploy Workers through this flow. A Custom API token is the only path.

### 4\. Account selection (only if you have more than one)

> **Agent:** Your session has access to 3 Cloudflare accounts:
> 
> 1. Personal (`a1b2c3...`)
> 2. Acme Corp (`e5f6g7...`)
> 3. Acme Staging (`i9j0k1...`)
> 
> Which one should hold the widget and Worker?

If there's only one account, the agent uses it without asking.

### 5\. Domain

The agent always includes `localhost` and `127.0.0.1` so local testing works without extra setup. For the production domain, it scans `package.json` (homepage field), `wrangler.toml`, `wrangler.jsonc`, `README.md`, `AGENTS.md`, and the git remote for a hint.

If it finds one, it confirms in a single line:

> **Agent:** I'll register the widget for `localhost`, `127.0.0.1`, and `example.com`. OK?

If it can't find one:

> **Agent:** I'll include `localhost` and `127.0.0.1` for testing. What production domain(s) should I add?

### 6\. Codebase scan

Silent. The agent uses grep/ls against your project for a few seconds, looking for forms, auth routes, and submit endpoints. Nothing is written to disk during this step.

### 7\. Insertion plan

If the agent found exactly one obvious form, it confirms in one line:

> **Agent:** I'll add Turnstile to the form in `app/contact/page.tsx:14`. OK?

If multiple candidates exist, it shows a list:

> **Agent:** I found 4 candidates for Turnstile protection:
> 
> 1. `app/(auth)/signup/page.tsx` (public signup form) \[recommended\]
> 2. `app/(auth)/login/page.tsx` (public login form) \[recommended\]
> 3. `app/contact/page.tsx` (public contact form) \[recommended\]
> 4. `app/admin/users/page.tsx` (admin form) \[skip by default\]
> 
> Reply with the numbers to protect, "all", "recommended", or a list like "1,3".

This is the most important confirmation in the flow. Do not let the agent proceed without one.

**If existing CAPTCHA is detected,** the insertion plan switches into a migration plan:

> **Agent:** I found existing reCAPTCHA usage in 3 files:
> 
> 1. `app/(auth)/signup/page.tsx`: reCAPTCHA v3 (sitekey `6Le...`)
> 2. `app/(auth)/login/page.tsx`: reCAPTCHA v3 (sitekey `6Le...`)
> 3. `app/api/verify-signup/route.ts`: siteverify call to `www.google.com/recaptcha/api/siteverify`
> 
> I can migrate these to Turnstile in place: swap the script tag, the widget div, and the siteverify endpoint, and remove the reCAPTCHA secret reference. Proceed?

See [Migrating from reCAPTCHA or hCaptcha](#migrating-from-recaptcha-or-hcaptcha) below for the detection signals and substitution rules.

### 8\. Widget creation

After your confirmation, the agent calls the Cloudflare API. No further input needed.

> **Agent:** Widget "myproject (Spin)" created. Site key `0x4AAAAAA...`. Stored the secret as a Worker secret, not on disk.

### 9\. Worker deploy

The agent copies the bundled Worker template into a temp directory, sets `TURNSTILE_SECRET_KEY`, and runs `wrangler deploy`.

> **Agent:** Deploying `turnstile-siteverify`... done. Worker URL: `https://turnstile-siteverify-myproject.example.workers.dev`

### 10\. Frontend edits (diff preview before write)

> **Agent:** I'm about to edit these 3 files:
> 
> * `app/(auth)/signup/page.tsx` (add Turnstile widget, wire form to Worker)
> * `app/(auth)/login/page.tsx` (same)
> * `app/contact/page.tsx` (same)
> 
> Reply "yes" to apply, "show" to see the diffs first.

If you reply "show", the agent prints unified diffs and asks again before writing.

### 11\. Validation

Three checks. The agent runs them and reports each:

> **Agent:**
> 
> * ✓ Worker `/health` returns `{"ok": true, "version": "..."}`
> * ✓ Worker handles a dummy token with a structured error (`success: false`, `error-codes: [...]`, `_worker` present)
> * ✓ Widget hostname matches `example.com`

If any check fails, the agent stops and explains. No further changes until you respond.

### 12\. Persist the skill

> **Agent:** I'm saving a copy of the Spin skill to `.claude/skills/turnstile-spin/SKILL.md` so I can pick it up on follow-up tasks ("add Turnstile to this new form", "debug a rejected token"). OK?

Default to yes. If the user has `.gitignore` patterns you'd violate, surface that.

### 13\. Final report

> **Agent:** Turnstile Spin: complete.
> 
> Created:
> 
> * Widget "myproject (Spin)", sitekey `0x4AAAAAA...`
> * Worker `https://turnstile-siteverify-myproject.example.workers.dev`
> * Frontend snippets at `app/(auth)/signup/page.tsx`, `app/(auth)/login/page.tsx`, `app/contact/page.tsx`
> * Skill saved at `.claude/skills/turnstile-spin/SKILL.md`
> 
> Validated: all 3 checks passed.
> 
> Next: open one of the protected forms in a browser, solve the widget, confirm the form submits successfully.

### Things the agent should NOT do

* Do not write the Turnstile secret to disk. Only pass it to `wrangler secret put` via stdin.
* Do not skip the validation step. The wizard's promise is that the integration is real, not just scaffolded.
* Do not overwrite existing files without showing a diff and getting explicit confirmation.
* Do not deploy a Worker to a different account than the widget was created in.
* Do not call siteverify directly from the browser. Always: browser → user's Worker → siteverify.

## What Spin does

Turnstile setup is a two-step problem. Step 1 renders the widget on the page. Step 2 calls [siteverify](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/) on a server. Today, most accounts complete step 1 and never finish step 2, so the widget renders but does not protect anything. Spin closes both steps in one flow.

The agent runs the full wizard in your project:

1. Scans your codebase, identifies forms, auth routes, and submit endpoints that should be protected, proposes a list.
2. Creates a Turnstile widget through the Cloudflare API. No dashboard click, no manual key copy-paste.
3. Deploys the managed siteverify Worker template (bundled with this skill at `templates/worker/`) into your Cloudflare account.
4. Writes the widget snippet at every chosen insertion point, with `data-action="turnstile-spin-v1"`.
5. Runs a real siteverify call against the deployed Worker with a dummy token, confirms the structured error, verifies hostname matches your domain.
6. Saves the skill into your repo so the agent stays useful for follow-up work like "add Turnstile to this new form" or "debug this rejected token".

### What gets created

| Artifact                        | Where it lives                                        | Path                                                 |
| ------------------------------- | ----------------------------------------------------- | ---------------------------------------------------- |
| Turnstile widget                | Cloudflare account                                    | dashboard, widget list                               |
| Managed siteverify Worker       | Cloudflare account, default subdomain or custom route | dashboard, Workers list                              |
| Frontend widget snippet         | Your repo, at each chosen insertion point             | varies by framework                                  |
| Secret (TURNSTILE\_SECRET\_KEY) | Worker secret, never on disk                          | Workers secret store                                 |
| Spin skill copy                 | Your repo                                             | .claude/skills/turnstile-spin/SKILL.md or equivalent |

---

## Wizard flow (for the agent)

This section is the agent's runbook. Each step is required unless the step itself says it is optional. If a step fails, surface the error to the user before continuing.

### Step 1: Authentication check

Confirm the user has a Cloudflare API token with the required scopes before running any provisioning. The token must carry `Account.Turnstile:Edit` and `Account.Workers Scripts:Edit`, with the target account included in Account Resources. `wrangler login` (OAuth) does not include either scope, so it is not a viable substitute.

Terminal window

```

npx wrangler whoami --json


```

Expected: JSON showing the authenticated email and an `accounts` array. If it errors or returns no accounts, the user needs to create a token at [https://dash.cloudflare.com/profile/api-tokens ↗](https://dash.cloudflare.com/profile/api-tokens) and export it as `CLOUDFLARE_API_TOKEN` before continuing.

If the token covers multiple accounts, `wrangler whoami --json` lists them under `accounts`. Prompt the user to choose, then export `CLOUDFLARE_ACCOUNT_ID` to that account's ID. Do not write it to a file.

### Step 2: Codebase scan

Identify candidate insertion points AND any existing CAPTCHA implementations that should be migrated. The goal is to propose every form, auth route, and submit endpoint that should be protected, plus any existing reCAPTCHA / hCaptcha code that should be replaced, then let the user prune.

Before the framework detection below, scan for existing CAPTCHA signals (see [Migrating from reCAPTCHA or hCaptcha](#migrating-from-recaptcha-or-hcaptcha) for the full list). If any are found, the wizard switches from "fresh insertion" mode to "migration" mode for those files.

Run this detection in order:

1. Detect framework. Look for these files at the project root:  
| Marker file                 | Framework               |  
| --------------------------- | ----------------------- |  
| next.config.{js,mjs,ts}     | Next.js                 |  
| astro.config.{mjs,ts}       | Astro                   |  
| svelte.config.{js,ts}       | SvelteKit               |  
| remix.config.{js,ts}        | Remix                   |  
| hugo.toml / config.toml     | Hugo                    |  
| wrangler.toml \+ functions/ | Cloudflare Pages        |  
| none of the above           | vanilla HTML (fallback) |  
If the project has both `next.config.*` and a `pages/` directory, treat as Next.js Pages Router. If it has `app/` instead, treat as Next.js App Router.
2. Find candidate insertion points by grep. Heuristics:  
   * Any element matching `<form ...>` in `.html`, `.tsx`, `.jsx`, `.astro`, `.svelte`, or `.vue` files.  
   * Any handler exporting `POST` in `app/api/**/route.{ts,js}` (Next.js App Router) or `pages/api/**/*.{ts,js}` (Pages Router).  
   * Any `+server.ts` or `+page.server.ts` in SvelteKit.  
   * Any `action.ts` or `action()` export in Remix.  
   * Files named `signup.*`, `login.*`, `register.*`, `contact.*`, `subscribe.*`, regardless of extension.
3. For each candidate, capture: file path, line number, surrounding context (the form element or handler signature), and whether it appears to be public-facing (no auth wrapper around the route).

### Step 3: User confirmation

Present the candidate list as a numbered list, marked by file path. Default-recommend protecting all public-facing form endpoints. Default-skip admin or already-authenticated routes.

Ask the user to confirm or edit:

```

I found 4 candidates for Turnstile protection:


  1. app/(auth)/signup/page.tsx  (public signup form)  [recommended]

  2. app/(auth)/login/page.tsx  (public login form)    [recommended]

  3. app/contact/page.tsx  (public contact form)       [recommended]

  4. app/admin/users/page.tsx  (admin form)            [skip by default]


Reply with the numbers to protect, or "all" / "recommended" / a list like "1,3".


```

Do not proceed until the user responds.

### Step 4: Create widget

Call the Cloudflare API to create a Turnstile widget. One widget covers all insertion points in the project. Use the user's domain as the widget hostname.

Request

```

POST https://api.cloudflare.com/client/v4/accounts/{account_id}/challenges/widgets

Authorization: Bearer {api_token}

Content-Type: application/json


{

  "name": "{project-name} (Spin)",

  "domains": ["example.com", "www.example.com"],

  "mode": "managed",

  "bot_fight_mode": false,

  "region": "world"

}


```

Wrangler does not currently expose a `turnstile` subcommand, so create the widget by calling the Cloudflare API directly. The Spin skill ships `scripts/widget-create.sh` which wraps this call; the equivalent raw `curl` is:

Terminal window

```

ACCOUNT_ID="${CLOUDFLARE_ACCOUNT_ID:-$(npx wrangler whoami --json | jq -r '.accounts[0].id')}"

curl -X POST \

  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/challenges/widgets" \

  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  -H "Content-Type: application/json" \

  -d '{"name":"myproject (Spin)","domains":["example.com"],"mode":"managed"}'


```

Expected response shape:

```

{

  "result": {

    "sitekey": "0x4AAAAAAA...",

    "secret": "0x4AAAAAAA...",

    "name": "myproject (Spin)",

    "domains": ["example.com"],

    "mode": "managed",

    "created_on": "2026-05-29T..."

  },

  "success": true

}


```

Capture `result.sitekey` and `result.secret`. The site key is public and will be written into the frontend snippet. The secret is private and will be set as a Worker secret in Step 5\. Do not write the secret to disk.

### Step 5: Deploy managed Worker

Deploy the managed siteverify Worker into the user's account using the template bundled with this skill at `templates/worker/`.

Terminal window

```

npx --yes degit cloudflare/skills/skills/turnstile-spin/templates/worker \

  /tmp/turnstile-siteverify-deploy


cd /tmp/turnstile-siteverify-deploy


# Deploy first so the named Worker exists

npx wrangler deploy --name turnstile-siteverify-{project-slug}


# Then set the secret on that named Worker (not on the wrangler.toml default)

echo "$WIDGET_SECRET" | npx wrangler secret put TURNSTILE_SECRET_KEY --name turnstile-siteverify-{project-slug}


```

`wrangler deploy` prints the deployed Worker URL, for example `https://turnstile-siteverify-myproject.example.workers.dev`. Capture it as `WORKER_URL`.

If the project is on Cloudflare Pages, deploy to the same account but as a separate Worker rather than a Pages Function. The [Pages Plugin for Turnstile](https://developers.cloudflare.com/pages/functions/plugins/turnstile/) covers Pages-native integration; Spin uses the managed Worker for consistency across stacks.

If `wrangler deploy` fails because the Worker name is taken, append a short random suffix and retry:

Terminal window

```

WORKER_NAME="turnstile-siteverify-{project-slug}-$(openssl rand -hex 3)"

npx wrangler deploy --name "$WORKER_NAME"


```

If the secret-put succeeds but `wrangler secret put` returns non-zero (`set_secret_failed` from `scripts/worker-deploy.sh`), the Worker is deployed but `TURNSTILE_SECRET_KEY` is not set. Re-run only the secret-put without redeploying:

Terminal window

```

echo "$WIDGET_SECRET" | npx wrangler secret put TURNSTILE_SECRET_KEY --name <worker_name from worker-deploy.sh output>


```

The script's error JSON includes a `detail` field carrying the wrangler error — surface it to the user verbatim.

#### Direct API alternative

If `wrangler` is unavailable, deploy by uploading the bundled script directly:

```

PUT https://api.cloudflare.com/client/v4/accounts/{account_id}/workers/scripts/{worker_name}

Authorization: Bearer {api_token}

Content-Type: multipart/form-data; boundary=...


```

The request body is multipart with `metadata` and `script` parts. See the [Workers API reference](https://developers.cloudflare.com/api/operations/worker-script-upload-worker-module) for the exact shape. The wrangler path above is strongly preferred.

### Step 6: Write frontend snippets

For each insertion point chosen in Step 3, write the appropriate snippet from the [Code examples](#code-examples) section below. Every snippet must include:

* `data-action="turnstile-spin-v1"` on the widget element (this is the telemetry marker, do not omit it).
* `data-sitekey` set to the site key from Step 4.
* A submit handler that POSTs the token to the Worker URL from Step 5, checks `success === true`, and only then delegates to **whatever the user's existing submit logic was**.

**Two contracts to respect, in priority order:**

1. **Do not** point the form `action` or top-level `fetch` directly at the Worker URL. The Worker is a siteverify proxy — it returns `{ success: true | false }`, it does not persist form data or call any other endpoint. Replacing the form target with the Worker URL silently drops every submission.
2. **Do not** replace the user's existing submit logic with a hardcoded call to `/api/subscribe` or any other URL the agent invented. Spin's role is to wrap the existing handler with a verification gate, not to write a new backend integration. The examples below show the gate; the line marked `/* existing submit logic */` is where the user's pre-existing code (their `fetch`, their `axios`, their form action, their server action) goes unchanged.

If the user already has a JS submit handler doing AJAX or framework navigation, modify that handler in place — add the gate at the top, keep the rest of its body. If the form had only a native `action="..."` attribute (no JS handler), then a small wrapping listener that ends with `form.submit()` is the right shape; the native form action then POSTs to the user's endpoint as it did before.

If the user uses a framework with a managed component (e.g. `@marsidev/react-turnstile`), prefer the component over hand-rolled HTML. The marker still goes on the component's `action` prop.

Do not overwrite existing files without showing a diff and getting explicit confirmation. Use a temp file or in-memory patch for the diff preview.

### Step 7: Validate

Before reporting success, run three checks against the deployed Worker.

#### 7a. Health endpoint

Terminal window

```

curl -sf "${WORKER_URL}/health"


```

Expected response (HTTP 200):

```

{ "ok": true, "version": "1.0.0" }


```

If the request fails or `ok` is not `true`, the Worker is not reachable. Re-run `wrangler deploy` and try again.

#### 7b. Dummy siteverify

Send a deliberately-invalid token and assert the Worker returns a structured error rather than a bare 500.

Terminal window

```

curl -s -X POST "${WORKER_URL}/" \

  -H "Content-Type: application/json" \

  -d '{"token":"XXXX.DUMMY.TOKEN.XXXX"}'


```

Expected response (HTTP 200, with `success: false`):

```

{

  "success": false,

  "error-codes": ["invalid-input-response"],

  "_worker": {

    "duration_ms": 87,

    "worker_version": "1.0.0"

  }

}


```

The exact `error-codes` value may differ depending on how upstream handles the dummy token. The required assertions are:

* `success` is `false`.
* `error-codes` is a non-empty array.
* `_worker` metadata is present.

If `_worker` is missing, the user's Worker is not the managed template (they may have deployed something custom). Alert them.

#### 7c. Hostname configuration

Verify the widget hostname matches the user's domain by calling the API directly (wrangler has no `turnstile` subcommand):

Terminal window

```

curl -sS \

  "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/challenges/widgets/${SITEKEY}" \

  -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \

  | jq '.result.domains'


```

The `domains` array should include the domains you registered in [Step 4: Create a Turnstile widget](#step-4-create-a-turnstile-widget). If it does not, you registered the wrong hostname. Update via `PUT` (not `PATCH`, which returns `10405`):

Terminal window

```

curl -sS -X PUT \

  "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/challenges/widgets/${SITEKEY}" \

  -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \

  -H "Content-Type: application/json" \

  -d '{"name":"myproject (Spin)","mode":"managed","domains":["example.com","www.example.com"]}'


```

#### 7d. Local dev check (optional)

If the user has a local dev server running on `localhost:3000` (or similar), make a request to confirm the frontend loads:

Terminal window

```

curl -sf "http://localhost:3000/" | grep -q 'cf-turnstile' \

  && echo "Widget snippet present" \

  || echo "Widget snippet not found in served HTML"


```

This is best-effort. If the user is not running a dev server, skip.

### Step 8: Persist the skill

Copy the Spin skill into the user's repo so the agent stays useful for follow-up tasks.

Terminal window

```

mkdir -p .claude/skills/turnstile-spin

curl -sSL https://developers.cloudflare.com/turnstile/spin/index.md \

  -o .claude/skills/turnstile-spin/SKILL.md


```

For other agents:

| Agent        | Persist path                             |
| ------------ | ---------------------------------------- |
| Claude Code  | .claude/skills/turnstile-spin/SKILL.md   |
| Cursor       | .cursor/rules/turnstile-spin.md          |
| Codex        | .codex/skills/turnstile-spin/SKILL.md    |
| OpenCode     | .opencode/skills/turnstile-spin/SKILL.md |
| Copilot Chat | .github/copilot/skills/turnstile-spin.md |
| Windsurf     | .windsurf/rules/turnstile-spin.md        |

If the project already has one of these directories from a prior install, overwrite the skill file (the docs page is the source of truth and changes over time). If not, create the directory.

Add the directory to `.gitignore` if the user prefers not to commit it, otherwise leave it tracked.

### Step 9: Report

Output a final summary to the user:

```

Turnstile Spin: complete.


Created:

  • Widget "myproject (Spin)", sitekey 0x4AAAAAA...

  • Worker https://turnstile-siteverify-myproject.example.workers.dev

  • Frontend snippets at:

    - app/(auth)/signup/page.tsx

    - app/(auth)/login/page.tsx

    - app/contact/page.tsx

  • Skill saved at .claude/skills/turnstile-spin/SKILL.md


Validated:

  ✓ Worker /health returns 200

  ✓ Worker handles a dummy token with a structured error

  ✓ Widget hostname matches example.com


Next:

  • Open one of the protected forms in a browser, solve the widget, and

    confirm the form submits successfully.

  • If you need to protect a new form later, prompt: "Use the

    turnstile-spin skill to add Turnstile to <file>."


```

If anything failed, include it as a caveat with the specific failure mode and the remediation step.

---

## Migrating from reCAPTCHA or hCaptcha

When the agent's codebase scan (Step 6 of the conversation flow, Step 2 of the wizard flow) finds existing reCAPTCHA or hCaptcha implementations, it switches into a migration plan instead of a fresh-insertion plan.

### Detection signals

| Signal                   | Pattern                                                                        | What it means              |
| ------------------------ | ------------------------------------------------------------------------------ | -------------------------- |
| reCAPTCHA v2 / v3 script | https://www.google.com/recaptcha/api.js (with or without ?render=)             | Frontend uses reCAPTCHA    |
| reCAPTCHA widget         | class="g-recaptcha" or data-sitekey="6L..." (reCAPTCHA sitekeys start with 6L) | Widget element             |
| reCAPTCHA backend        | https://www.google.com/recaptcha/api/siteverify in any server-side file        | siteverify call to replace |
| hCaptcha script          | https://js.hcaptcha.com/1/api.js                                               | Frontend uses hCaptcha     |
| hCaptcha widget          | class="h-captcha" or hCaptcha-shaped sitekey (UUID-style)                      | Widget element             |
| hCaptcha backend         | https://hcaptcha.com/siteverify in any server-side file                        | siteverify call to replace |

### Substitution rules

| What to find                                              | What to replace it with                                                                                                                                                                                                                                    |
| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <script src="https://www.google.com/recaptcha/api.js"...> | <script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>                                                                                                                                                                  |
| <script src="https://js.hcaptcha.com/1/api.js"...>        | Same as above.                                                                                                                                                                                                                                             |
| <div class="g-recaptcha" data-sitekey="6L..."></div>      | <div class="cf-turnstile" data-sitekey="YOUR\_TURNSTILE\_SITEKEY" data-action="turnstile-spin-v1"></div>                                                                                                                                                   |
| <div class="h-captcha" data-sitekey="..."></div>          | Same as above.                                                                                                                                                                                                                                             |
| grecaptcha.execute(...) / grecaptcha.render(...) calls    | turnstile.render(...) / turnstile.execute(...) with the same callbacks. Delete any manual <input name="g-recaptcha-response"> — Turnstile renders cf-turnstile-response itself.                                                                            |
| https://www.google.com/recaptcha/api/siteverify POST      | The Spin-deployed managed Worker URL. Drop the secret field (the Worker holds it). The Worker accepts token, cf-turnstile-response, **or** response for drop-in compatibility, plus optional remoteip. Response shape (success, error-codes) is identical. |
| RECAPTCHA\_SECRET / HCAPTCHA\_SECRET env var              | Remove. The Turnstile secret lives in the managed Worker as a Worker secret, never in the customer's app env.                                                                                                                                              |

### Edge cases

* **reCAPTCHA v3 score thresholds.** If the customer's backend rejects on `score < 0.5` or similar, Turnstile has no equivalent score field. The agent should warn: "Your reCAPTCHA v3 verifier checks a score threshold. Turnstile doesn't expose a score; it returns `success: true/false`. The migrated code will reject on `success === false` only. Adjust your downstream logic if needed."
* **reCAPTCHA Enterprise.** Different API surface from regular reCAPTCHA. If the agent sees `recaptchaenterprise.googleapis.com` calls, do not auto-migrate. Tell the user: "I see reCAPTCHA Enterprise. The migration path is different and not yet automated. See [the Cloudflare migration guide for reCAPTCHA](https://developers.cloudflare.com/turnstile/migration/recaptcha/) and re-run Spin once you've handled the Enterprise specifics."
* **Per-action data (`data-action`, `cdata`).** Preserve any `action=` parameter passed to `grecaptcha.execute` as `data-action` on the Turnstile widget. If the user had a custom action, keep it; the Spin marker `data-action="turnstile-spin-v1"` is the default only when no action is set.
* **Mixed usage.** If only some routes use reCAPTCHA and others have no CAPTCHA, the migration plan covers the reCAPTCHA routes and the regular insertion plan covers the rest. Present both in the same Step 7 confirmation.

### Reference

The exhaustive migration guides live at:

* [Migrating from reCAPTCHA](https://developers.cloudflare.com/turnstile/migration/recaptcha/)
* [Migrating from hCaptcha](https://developers.cloudflare.com/turnstile/migration/hcaptcha/)

The agent should fetch one or both of these when it needs the exact replacement pattern for a framework-specific case (e.g. `react-google-recaptcha`, `@hcaptcha/react-hcaptcha`).

## Code examples

Snippets per framework. Every snippet carries `data-action="turnstile-spin-v1"`. Substitute `YOUR_SITEKEY` and `YOUR_WORKER_URL` with the values from Steps 4 and 5.

* [  Vanilla HTML ](#tab-panel-10880)
* [  Next.js (App Router) ](#tab-panel-10881)
* [  Next.js (Pages Router) ](#tab-panel-10882)
* [  Astro ](#tab-panel-10883)
* [  SvelteKit ](#tab-panel-10884)
* [  Hugo ](#tab-panel-10885)

index.html

```

<!doctype html>

<html>

  <head>

    <script

      src="https://challenges.cloudflare.com/turnstile/v0/api.js"

      async

      defer

    ></script>

  </head>

  <body>

    <form id="signup-form" action="/api/subscribe" method="POST">

      <input name="email" type="email" required />

      <div

        class="cf-turnstile"

        data-sitekey="YOUR_SITEKEY"

        data-action="turnstile-spin-v1"

      ></div>

      <button type="submit">Subscribe</button>

      <p id="signup-error" hidden>Verification failed. Try again.</p>

    </form>

    <script>

      document

        .getElementById("signup-form")

        .addEventListener("submit", async (e) => {

          e.preventDefault();

          const form = e.currentTarget;

          const token = form.querySelector(

            '[name="cf-turnstile-response"]',

          ).value;

          // Gate on the Spin Worker (siteverify). On success, submit to your real endpoint.

          const verify = await fetch("https://YOUR_WORKER_URL/", {

            method: "POST",

            headers: { "Content-Type": "application/json" },

            body: JSON.stringify({ token }),

          });

          const { success } = await verify.json();

          if (!success) {

            document.getElementById("signup-error").hidden = false;

            return;

          }

          form.submit();

        });

    </script>

  </body>

</html>


```

app/signup/page.tsx

```

"use client";

import Script from "next/script";

import { useEffect, useState } from "react";


declare global {

  interface Window {

    onTurnstileSuccess?: (token: string) => void;

  }

}


export default function SignupPage() {

  const [token, setToken] = useState("");

  const [error, setError] = useState("");


  useEffect(() => {

    window.onTurnstileSuccess = (t: string) => setToken(t);

  }, []);


  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {

    e.preventDefault();

    setError("");

    // Gate on the Spin Worker (siteverify).

    const verify = await fetch("https://YOUR_WORKER_URL/", {

      method: "POST",

      headers: { "Content-Type": "application/json" },

      body: JSON.stringify({ token }),

    });

    const { success } = await verify.json();

    if (!success) {

      setError("Verification failed. Try again.");

      return;

    }

    // On success, run the user's existing submit logic — whatever it was.

    // e.g. a fetch to /api/subscribe, a server action, a router.push, etc.

    /* existing submit logic */

  }


  return (

    <>

      <Script

        src="https://challenges.cloudflare.com/turnstile/v0/api.js"

        strategy="afterInteractive"

      />

      <form onSubmit={handleSubmit}>

        <input name="email" type="email" required />

        <div

          className="cf-turnstile"

          data-sitekey="YOUR_SITEKEY"

          data-action="turnstile-spin-v1"

          data-callback="onTurnstileSuccess"

        />

        <button type="submit" disabled={!token}>

          Sign up

        </button>

        {error && <p>{error}</p>}

      </form>

    </>

  );

}


```

pages/signup.tsx

```

import Script from "next/script";

import { useState } from "react";


declare global {

  interface Window {

    onTurnstileSuccess?: (token: string) => void;

  }

}


export default function SignupPage() {

  const [token, setToken] = useState("");

  const [error, setError] = useState("");


  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {

    e.preventDefault();

    setError("");

    const verify = await fetch("https://YOUR_WORKER_URL/", {

      method: "POST",

      headers: { "Content-Type": "application/json" },

      body: JSON.stringify({ token }),

    });

    const { success } = await verify.json();

    if (!success) {

      setError("Verification failed. Try again.");

      return;

    }

    // On success, run the user's existing submit logic — whatever it was.

    /* existing submit logic */

  }


  return (

    <>

      <Script

        src="https://challenges.cloudflare.com/turnstile/v0/api.js"

        onLoad={() => {

          window.onTurnstileSuccess = (t: string) => setToken(t);

        }}

      />

      <form onSubmit={handleSubmit}>

        <input name="email" type="email" required />

        <div

          className="cf-turnstile"

          data-sitekey="YOUR_SITEKEY"

          data-action="turnstile-spin-v1"

          data-callback="onTurnstileSuccess"

        />

        <button type="submit" disabled={!token}>

          Sign up

        </button>

        {error && <p>{error}</p>}

      </form>

    </>

  );

}


```

src/pages/signup.astro

```

---

const WORKER_URL = "https://YOUR_WORKER_URL";

---


<html>

  <head>

    <script

      src="https://challenges.cloudflare.com/turnstile/v0/api.js"

      async

      defer

    ></script>

  </head>

  <body>

    <form id="signup-form" action="/api/subscribe" method="POST">

      <input name="email" type="email" required />

      <div

        class="cf-turnstile"

        data-sitekey="YOUR_SITEKEY"

        data-action="turnstile-spin-v1"

      />

      <button type="submit">Sign up</button>

      <p id="signup-error" hidden>Verification failed. Try again.</p>

    </form>

    <script define:vars={{ WORKER_URL }}>

      document

        .getElementById("signup-form")

        .addEventListener("submit", async (e) => {

          e.preventDefault();

          const form = e.currentTarget;

          const token = form.querySelector(

            '[name="cf-turnstile-response"]',

          ).value;

          const verify = await fetch(WORKER_URL + "/", {

            method: "POST",

            headers: { "Content-Type": "application/json" },

            body: JSON.stringify({ token }),

          });

          const { success } = await verify.json();

          if (!success) {

            document.getElementById("signup-error").hidden = false;

            return;

          }

          form.submit();

        });

    </script>

  </body>

</html>


```

src/routes/signup/+page.svelte

```

<script lang="ts">

  import { onMount } from "svelte";

  let token = "";

  let error = "";


  onMount(() => {

    (window as any).onTurnstileSuccess = (t: string) => (token = t);

  });


  async function handleSubmit(e: SubmitEvent) {

    e.preventDefault();

    error = "";

    const verify = await fetch("https://YOUR_WORKER_URL/", {

      method: "POST",

      headers: { "Content-Type": "application/json" },

      body: JSON.stringify({ token }),

    });

    const { success } = await verify.json();

    if (!success) {

      error = "Verification failed. Try again.";

      return;

    }

    // On success, run the user's existing submit logic — whatever it was.

    /* existing submit logic */

  }

</script>


<svelte:head>

  <script

    src="https://challenges.cloudflare.com/turnstile/v0/api.js"

    async

    defer

  ></script>

</svelte:head>


<form on:submit={handleSubmit}>

  <input name="email" type="email" required />

  <div

    class="cf-turnstile"

    data-sitekey="YOUR_SITEKEY"

    data-action="turnstile-spin-v1"

    data-callback="onTurnstileSuccess"

  ></div>

  <button type="submit" disabled={!token}>Sign up</button>

  {#if error}<p>{error}</p>{/if}

</form>


```

layouts/partials/turnstile.html

```

<script

  src="https://challenges.cloudflare.com/turnstile/v0/api.js"

  async

  defer

></script>


<form id="signup-form" action="/api/subscribe" method="POST">

  <input name="email" type="email" required />

  <div

    class="cf-turnstile"

    data-sitekey="{{ .Site.Params.turnstileSitekey }}"

    data-action="turnstile-spin-v1"

  ></div>

  <button type="submit">Subscribe</button>

  <p id="signup-error" hidden>Verification failed. Try again.</p>

</form>


<script>

  document

    .getElementById("signup-form")

    .addEventListener("submit", async (e) => {

      e.preventDefault();

      const form = e.currentTarget;

      const token = form.querySelector(

        '[name="cf-turnstile-response"]',

      ).value;

      const verify = await fetch(

        "{{ .Site.Params.turnstileWorkerUrl }}/",

        {

          method: "POST",

          headers: { "Content-Type": "application/json" },

          body: JSON.stringify({ token }),

        },

      );

      const { success } = await verify.json();

      if (!success) {

        document.getElementById("signup-error").hidden = false;

        return;

      }

      form.submit();

    });

</script>


```

Reference in any page or layout:

hugo.toml

```

[params]

turnstileSitekey = "YOUR_SITEKEY"

turnstileWorkerUrl = "https://YOUR_WORKER_URL"


```

---

## Edge cases and error handling

### Wrangler is not installed

If `npx wrangler` fails with `command not found`, prompt the user to install it:

Terminal window

```

npm install -g wrangler


```

If the user is in a non-Node project (Hugo, vanilla HTML), install locally instead:

Terminal window

```

npm init -y

npm install --save-dev wrangler


```

This is the only Node dependency Spin requires.

### Multiple Cloudflare accounts

`wrangler whoami` lists all accounts associated with the user's session. If there is more than one, prompt explicitly:

```

Your session has access to 3 Cloudflare accounts:

  1. Personal (a1b2c3d4...)

  2. Acme Corp (e5f6g7h8...)

  3. Acme Staging (i9j0k1l2...)


Which one should the widget and Worker be created in?


```

Set `CLOUDFLARE_ACCOUNT_ID` in the environment for the rest of the flow.

### User has Cloudflare Pages

If the user's project is on Cloudflare Pages, you have two valid options:

1. Deploy the managed Worker into the same account anyway (recommended; same Worker as every other Spin user).
2. Suggest the [Pages Plugin for Turnstile](https://developers.cloudflare.com/pages/functions/plugins/turnstile/), which runs in the Pages Functions runtime.

Default to option 1 unless the user explicitly wants the Pages-native path. The Spin telemetry marker still works either way.

### `EXPECTED_HOSTNAME` does not match

The managed Worker supports an `EXPECTED_HOSTNAME` env var. If set, the Worker rejects siteverify responses whose `hostname` field does not match. This defends against cross-site token replay.

If the user wants `EXPECTED_HOSTNAME` set:

Terminal window

```

npx wrangler deploy --var EXPECTED_HOSTNAME:"www.example.com"


```

If validation in Step 7 reports `hostname-mismatch`, either the widget is registered with a different domain than the request is coming from, or `EXPECTED_HOSTNAME` is wrong. Re-check both.

### Worker deploy fails

Common causes and fixes:

| Error                               | Cause                                                     | Fix                                                                                                                                                                               |
| ----------------------------------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| script name already in use          | Another Worker has the same name                          | Append a short random suffix: \--name turnstile-siteverify-{project}-$(openssl rand -hex 3)                                                                                       |
| no workers.dev subdomain configured | Account has no default subdomain                          | Set one in the dashboard, or deploy to a custom route                                                                                                                             |
| unauthorized                        | Token expired or missing Account.Workers Scripts:Edit     | Re-create the token at [https://dash.cloudflare.com/profile/api-tokens ↗](https://dash.cloudflare.com/profile/api-tokens) with the right scopes; re-export CLOUDFLARE\_API\_TOKEN |
| secret not set                      | TURNSTILE\_SECRET\_KEY was not pushed to the named Worker | Run echo "$WIDGET\_SECRET" \| npx wrangler secret put TURNSTILE\_SECRET\_KEY --name <worker\_name>                                                                                |
| 522 on first request after deploy   | Cold-start race                                           | Wait 5-10 seconds, retry the validation curl                                                                                                                                      |

If the deploy fails for any other reason, surface the wrangler error verbatim to the user. Do not retry blindly.

### Widget creation API returns 403

This usually means the account does not have Turnstile enabled, or the user's token lacks the `Account.Turnstile:Edit` permission. Direct the user to the [Turnstile dashboard ↗](https://dash.cloudflare.com/?to=/:account/turnstile) and have them confirm Turnstile is available. If it is and the API still 403s, the token is the problem; re-create it at [https://dash.cloudflare.com/profile/api-tokens ↗](https://dash.cloudflare.com/profile/api-tokens) with `Account.Turnstile:Edit` (and `Account.Workers Scripts:Edit` for the next step) and re-export `CLOUDFLARE_API_TOKEN`.

---

## Recovery flow (existing widget)

If the user already set up a Turnstile widget manually and got stuck on the siteverify step, Spin can wire up the backend against the existing widget without changing the site key.

The recovery entry point is verbal — the user tells the agent they already have a widget. Typical phrasings:

> "I already have a Turnstile sitekey but siteverify never worked, can you help wire it up?"
> 
> "Set up Spin against my existing widget `0x4AAAAAAA...`"

When the agent detects this intent, it modifies the wizard flow:

1. Skip [Step 4: Create a Turnstile widget](#step-4-create-a-turnstile-widget). Ask the user for the sitekey if they did not include it. Then fetch the widget metadata + secret by calling `scripts/fetch-secret.sh --account-id <id> --sitekey <key>`. The script returns `secret`, `clearance_level`, and `domains`. If `status` is `missing_read_scope`, ask the user to add `Account.Turnstile:Read` to the token or to paste the secret manually.
2. If `clearance_level` is not `no_clearance`, ask whether the user wants siteverify on top of pre-clearance. If not, exit per the [Hard scope boundary](#hard-scope-boundary-do-not-ask-the-user-about) and redirect them.
3. Confirm `domains` already includes the user's production hostname. If not, surface the gap and update the widget via the `curl -X PUT` shown in [Step 7c](#7c-hostname-configuration) before proceeding.
4. Proceed to [Step 5: Deploy the managed siteverify Worker](#step-5-deploy-the-managed-siteverify-worker) using the captured secret.
5. In [Step 6: Write frontend snippets](#step-6-write-frontend-snippets), check whether the user already has widget HTML in their codebase. If they do, prompt before overwriting:  
```  
You already have a Turnstile widget in 3 files:  
  • app/signup/page.tsx  
  • app/login/page.tsx  
  • app/contact/page.tsx  
Would you like me to update these to point at the new Worker URL  
and add the data-action marker? (yes / no / per-file)  
```
6. Continue with [Step 7: Validate](#step-7-validate), [Step 8: Persist the skill](#step-8-persist-the-skill), and [Step 9: Report](#step-9-report-and-handoff) as normal.

Never recreate the widget to get a fresh secret — that rotates the sitekey everywhere the user has it deployed.

The site key never changes. The user's existing widget keeps working throughout. The dashboard's `Deployment` column updates from `Manual` to `Spin` once the first request with `data-action="turnstile-spin-v1"` lands.

---

## Reference

### Managed Worker endpoints

The deployed Worker exposes three endpoints.

| Method | Path        | Purpose                                               |
| ------ | ----------- | ----------------------------------------------------- |
| POST   | /           | Siteverify proxy. Accepts JSON or form-encoded body.  |
| POST   | /siteverify | Alias of /.                                           |
| GET    | /health     | Health check. Returns {"ok": true, "version": "..."}. |
| GET    | /           | Returns the same payload as /health for convenience.  |

Request body (JSON):

```

{

  "token": "TURNSTILE_TOKEN_FROM_WIDGET",

  "remoteip": "1.2.3.4",

  "idempotency_key": "optional-uuid"

}


```

The Worker forwards the token to `https://challenges.cloudflare.com/turnstile/v0/siteverify` with the secret from `TURNSTILE_SECRET_KEY` and returns the upstream response augmented with `_worker` timing metadata.

### Worker configuration

| Variable               | Type   | Default    | Purpose                                                           |
| ---------------------- | ------ | ---------- | ----------------------------------------------------------------- |
| TURNSTILE\_SECRET\_KEY | secret | (required) | The widget's secret. Never on disk.                               |
| ALLOWED\_ORIGIN        | var    | \*         | CORS allowed origin. Lock to your customer-facing domain in prod. |
| EXPECTED\_HOSTNAME     | var    | (unset)    | If set, reject siteverify responses with a mismatched hostname.   |

### Telemetry marker

Every Spin-deployed widget carries:

```

<div

  class="cf-turnstile"

  data-sitekey="YOUR_SITEKEY"

  data-action="turnstile-spin-v1"

></div>


```

The `action` field is preserved end-to-end through siteverify and surfaces as a queryable dimension in Turnstile Analytics. Cloudflare uses this to measure activation rates and time-to-first-siteverify for Spin-deployed widgets versus manual ones. The marker is account-level and aggregate. No PII, no per-user tracking. See the [Turnstile privacy addendum ↗](https://www.cloudflare.com/turnstile-privacy-policy/).

To opt out, remove the `data-action` attribute. The integration still works; only the deployment-method analytics are affected.

### Related

* [cloudflare/skills ↗](https://github.com/cloudflare/skills): skills bundle, includes `turnstile-spin/` and the bundled Worker template at `skills/turnstile-spin/templates/worker/`
* [Turnstile server-side validation](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/)
* [Test sitekeys and secrets](https://developers.cloudflare.com/turnstile/troubleshooting/testing/)
* [Pages Plugin for Turnstile](https://developers.cloudflare.com/pages/functions/plugins/turnstile/)
* [Workers secrets](https://developers.cloudflare.com/workers/configuration/secrets/)
* [Cloudflare Radar bot traffic ↗](https://radar.cloudflare.com/traffic/bot-classes)
* [Cloudflare Docs for Agents](https://developers.cloudflare.com/docs-for-agents/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/spin/","name":"Turnstile Spin (beta)"}}]}
```

---

---
title: Get started
description: Set up Turnstile to verify visitors without a traditional CAPTCHA.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Get started

Turnstile protects your website forms from bots. It works in two steps: a JavaScript widget runs challenges in the visitor's browser and produces a token, then your server sends that token to Cloudflare to confirm it is valid. This guide covers how to set up both steps.

## Prerequisites

Before you begin, you must have:

* [A Cloudflare account](https://developers.cloudflare.com/fundamentals/account/create-account/)
* A website or web application to protect
* Basic knowledge of HTML and your preferred server-side language

---

## Process

A Turnstile widget is an instance of Turnstile embedded on your webpage. Each widget has a sitekey (a public identifier you place in your HTML) and a secret key (a private credential your server uses to validate tokens).

Each widget gets its own unique sitekey and secret key pair, and options for configurations.

| Component      | Description                                                  |
| -------------- | ------------------------------------------------------------ |
| Sitekey        | Public key used to invoke the Turnstile widget on your site. |
| Secret key     | Private key used for server-side token validation.           |
| Configurations | Mode, hostnames, appearance settings, and other options.     |

Important

Regardless of how you create and manage your widgets, you will still need to [embed the widget](https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/) on your webpage and [validate the token](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/) on your server.

Implementing Turnstile involves two essential components that work together:

1. Client-side: [Embed the widget](https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/)  
Add the Turnstile widget to your webpage to challenge visitors and generate tokens. A token is a string (up to 2,048 characters) generated when the visitor completes a challenge.
2. Server-side: [Validate the token](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/)  
Send tokens to Cloudflare's [Siteverify API](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/) — the endpoint for validating Turnstile tokens — to confirm they are authentic and have not been tampered with.

Turnstile is designed to be an independent service. You can use Turnstile on any website, regardless of whether it is proxied through the Cloudflare network. This allows for flexible deployment across multi-cloud environments, on-premises infrastructure, or sites using other CDNs. The client-side widget and server-side validation steps are completely self-contained.

Refer to [Implementation](#implementation) below for guidance on how to implement Turnstile on your website.

---

## Implementation

Follow the steps below to implement Turnstile.

### 1\. Create your widget

First, you must create a Turnstile widget to get your sitekey and secret key.

Select your preferred implementation method:

[ Cloudflare dashboard ](https://developers.cloudflare.com/turnstile/get-started/widget-management/dashboard/) [ API ](https://developers.cloudflare.com/turnstile/get-started/widget-management/api/) [ Terraform ](https://developers.cloudflare.com/turnstile/get-started/widget-management/terraform/) 

### 2\. Embed the widget

Add the Turnstile widget to your webpage forms and applications.

Refer to [Embed the widget](https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/) to learn more about implicit and explicit rendering methods.

Testing

You can test your Turnstile widget on your webpage without triggering an actual Cloudflare Challenge by using a testing sitekey.

Refer to [Testing](https://developers.cloudflare.com/turnstile/troubleshooting/testing/) for more information.

### 3\. Validate tokens

Implement server-side validation to verify the tokens generated by your widgets.

Refer to [Validate the token](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/) to secure your implementation with proper token verification.

Testing

You can test the dummy token generated with testing sitekey via Siteverify API with the testing secret key. Your production secret keys will reject dummy tokens.

Refer to [Testing](https://developers.cloudflare.com/turnstile/troubleshooting/testing/) for more information.

## Additional implementation options

### Mobile configuration

Special considerations are necessary for mobile applications and WebView implementations.

Refer to [Mobile implementation](https://developers.cloudflare.com/turnstile/get-started/mobile-implementation/) for more information on mobile application integration.

### Migration from other CAPTCHAs

If you are currently using reCAPTCHA, hCaptcha, or another CAPTCHA service, Turnstile can be a drop-in replacement. You can copy and paste our script wherever you have deployed the existing script today.

Refer to [Migration](https://developers.cloudflare.com/turnstile/migration/) for step-by-step migration guidance from other CAPTCHA services.

---

## Security requirements

* Server-side validation is mandatory. It is critical to enforce Turnstile tokens with the Siteverify API. The Turnstile token could be invalid, expired, or already redeemed. Not verifying the token will leave major vulnerabilities in your implementation. You must call Siteverify to complete your Turnstile configuration. Otherwise, it is incomplete and will result in zeroes for token validation when viewing your metrics in [Turnstile Analytics](https://developers.cloudflare.com/turnstile/turnstile-analytics/).
* Tokens expire after 300 seconds (5 minutes). Each token can only be validated once. Expired or used tokens must be replaced with fresh challenges.

---

## Best practices

### Security

* Protect your secret keys. Never expose secret keys in client-side code.
* Rotate your keys regularly. Use API or dashboard to rotate secret keys periodically.
* Restrict your hostnames. Only allow widgets on domains that you control.
* Monitor the usage. Use analytics to detect unusual patterns.

### Operational

* Use descriptive names. Name widgets based on their purpose, such as "Login Form" or "Contact Page".
* Separate your environments. Use different widgets for development, staging, and production.
* Keep track of which widgets are used at which locations.
* Store your widget configurations in version control when using Terraform.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/get-started/","name":"Get started"}}]}
```

---

---
title: Embed the widget
description: Embed a Turnstile widget on your website with JavaScript or HTML.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Embed the widget

Learn how to add the Turnstile widget to your webpage using implicit or explicit rendering methods.

Turnstile offers two ways to add widgets to your page. **Implicit rendering** automatically scans your HTML for widget containers when the page loads. **Explicit rendering** gives you programmatic control to create widgets at any time using JavaScript. Use implicit rendering for static pages where forms exist at page load. Use explicit rendering for dynamic content and single-page applications (SPAs) where forms are created after the initial page load.

| Feature                 | Implicit rendering                 | Explicit rendering                 |
| ----------------------- | ---------------------------------- | ---------------------------------- |
| **Ease of setup**       | Simple, minimal code               | Requires additional JavaScript     |
| **Control over timing** | Renders automatically on page load | Full control over rendering timing |
| **Use cases**           | Static content                     | Dynamic or interactive content     |
| **Customization**       | Limited to HTML attributes         | Extensive via JavaScript API       |

## Prerequisites

Before you begin, you must have:

* A Cloudflare account
* [A Turnstile widget](https://developers.cloudflare.com/turnstile/get-started/#1-create-your-widget) with a sitekey
* Access to edit your website's HTML
* Basic knowledge of HTML and JavaScript

## Process

1. Page load: The Turnstile script loads and scans for elements or waits for programmatic calls.
2. Widget rendering: Widgets are created and begin running challenges.
3. Token generation: When a challenge is completed, a token is generated.
4. Form integration: The token is made available via callbacks or hidden form fields.
5. Server validation: Your server receives the token and validates it using the Siteverify API.

## Implicit rendering

Implicit rendering automatically scans your HTML for elements with the `cf-turnstile` class and renders widgets without additional JavaScript code. This set up is ideal for static pages where you want the widget to load immediately when the page loads.

### Use cases

Cloudflare recommends using implicit rendering on the following scenarios:

* You have simple implementations and want a quick integration.
* You have static websites with straightforward forms.
* You want widgets to appear immediately on pageload.
* You do not need programmatic control of the widget.

### Implementation

#### 1\. Add the Turnstile script

**Include the Turnstile Script**: Add the Turnstile JavaScript API to your HTML file within the `<head>` section or just before the closing `</body>` tag.

```

<script

  src="https://challenges.cloudflare.com/turnstile/v0/api.js"

  async

  defer

></script>


```

Warning

The `api.js` file must be fetched from the exact URL shown above. Proxying or caching this file will cause Turnstile to fail when future updates are released.

#### 2\. (Optional) Optimize performance with resource hints

Add resource hints to improve loading performance by establishing early connections to Cloudflare servers. Place this `<link>` tag in your HTML `<head>` section before the Turnstile script.

```

<link rel="preconnect" href="https://challenges.cloudflare.com" />


```

#### 3\. Add widget elements

Add widget containers where you want the challenges to appear on your website.

```

<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>


```

#### 4\. Configure with data attributes

[Customize your widgets](https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/widget-configurations/) using data attributes. Insert a `div` element where you want the widget to appear.

```

<div

  class="cf-turnstile"

  data-sitekey="<YOUR-SITE-KEY>"

  data-theme="light"

  data-size="normal"

  data-callback="onSuccess"

></div>


```

Once a challenge has been solved, a token is passed to the success callback. This token must be validated against our [Siteverify endpoint](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/).

### Complete implicit rendering examples by use case

Basic login form

Turnstile is often used to protect forms on websites such as login forms or contact forms. You can embed the widget within your `<form>` tag.

Example

```

<!DOCTYPE html>

<html>

<head>

    <title>Login Form</title>

    <script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

</head>

<body>

    <form action="/login" method="POST">

        <input type="text" name="username" placeholder="Username" required />

        <input type="password" name="password" placeholder="Password" required />


        <!-- Turnstile widget with basic configuration -->

        <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>

        <button type="submit">Log in</button>

    </form>


</body>

</html>


```

An invisible input with the name `cf-turnstile-response` is added and will be sent to the server with the other fields.

Complete HTML example

```

<!DOCTYPE html>

<html lang="en">

  <head>

    <meta charset="UTF-8" />

    <title>Implicit Rendering with Cloudflare Turnstile</title>

    <script

      src="https://challenges.cloudflare.com/turnstile/v0/api.js"

      async

      defer

    ></script>

  </head>

  <body>

    <h1>Contact Us</h1>

    <form action="/submit" method="POST">

      <label for="name">Name:</label><br />

      <input type="text" id="name" name="name" required /><br />

      <label for="email">Email:</label><br />

      <input type="email" id="email" name="email" required /><br />

      <!-- Turnstile Widget -->

      <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>

      <br />

      <button type="submit">Submit</button>

    </form>

  </body>

</html>


```

Advanced form with callbacks

Example

```

<form action="/contact" method="POST" id="contact-form">

  <input type="email" name="email" placeholder="Email" required />

  <textarea name="message" placeholder="Message" required></textarea>

  <!-- Widget with callbacks and custom configuration -->

  <div

    class="cf-turnstile"

    data-sitekey="<YOUR-SITE-KEY>"

    data-theme="auto"

    data-size="flexible"

    data-callback="onTurnstileSuccess"

    data-error-callback="onTurnstileError"

    data-expired-callback="onTurnstileExpired"

  ></div>

  <button type="submit" id="submit-btn" disabled>Send Message</button>

</form>


<script>

  function onTurnstileSuccess(token) {

    console.log("Turnstile success:", token);

    document.getElementById("submit-btn").disabled = false;

  }

  function onTurnstileError(errorCode) {

    console.error("Turnstile error:", errorCode);

    document.getElementById("submit-btn").disabled = true;

  }

  function onTurnstileExpired() {

    console.warn("Turnstile token expired");

    document.getElementById("submit-btn").disabled = true;

  }

</script>


```

Multiple widgets with different configurations

Example

```

<!-- Compact widget for newsletter signup -->

<form action="/newsletter" method="POST">

  <input type="email" name="email" placeholder="Email" />

  <div

    class="cf-turnstile"

    data-sitekey="<YOUR-SITE-KEY>"

    data-size="compact"

    data-action="newsletter"

  ></div>

  <button type="submit">Subscribe</button>

</form>


<!-- Normal widget for contact form -->

<form action="/contact" method="POST">

  <input type="text" name="name" placeholder="Name" />

  <input type="email" name="email" placeholder="Email" />

  <textarea name="message" placeholder="Message"></textarea>

  <div

    class="cf-turnstile"

    data-sitekey="<YOUR-SITE-KEY>"

    data-action="contact"

    data-theme="dark"

  ></div>

  <button type="submit">Send</button>

</form>


```

Automatic form integration

When you embed a Turnstile widget inside a `<form>` element, an invisible input field with the name `cf-turnstile-response` is automatically created. This field contains the verification token and gets submitted with your other form data.

```

<form action="/submit" method="POST">

  <input type="text" name="data" />

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>

  <!-- Hidden field automatically added: -->

  <!-- <input type="hidden" name="cf-turnstile-response" value="TOKEN_VALUE" /> -->

  <button type="submit">Submit</button>

</form>


```

---

## Explicit rendering

Explicit rendering gives you programmatic control over when and where the widget appears and how the widgets are created using JavaScript functions. This method is suitable for dynamic content, single-page applications (SPAs), or conditional rendering based on user interactions.

### Use cases

Cloudflare recommends using explicit rendering on the following scenarios:

* You have dynamic websites and single-page applications (SPAs).
* You need to control the timing of widget creation.
* You want to conditionally render the widget based on visitor interactions.
* You want multiple widgets with different configurations.
* You have complex applications requiring widget lifecycle management.

### Implementation

#### 1\. Add the script to your website with explicit rendering

```

<script

  src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"

  defer

></script>


```

#### 2\. Create container elements

Create containers without the `cf-turnstile` class.

```

<div id="turnstile-container"></div>


```

#### 3\. Render the widgets programmatically

Call `turnstile.render()` when you are ready to create the widget.

JavaScript

```

const widgetId = turnstile.render("#turnstile-container", {

  sitekey: "<YOUR-SITE-KEY>",

  callback: function (token) {

    console.log("Success:", token);

  },

});


```

### Optional calls

After rendering the Turnstile widget explicitly, you may need to interact with it based on your application's requirements. Refer to the sections below to manage the widget's state.

#### Reset a widget

To reset the widget if the given widget timed out or expired, you can use the function:

JavaScript

```

turnstile.reset(widgetId);


```

#### Get the response token

Retrieve the current response token at any time:

JavaScript

```

const responseToken = turnstile.getResponse(widgetId);


```

#### Remove a widget

When a widget is no longer needed, it can be removed from the page using:

JavaScript

```

turnstile.remove(widgetId);


```

This will not call any callback and will remove all related DOM elements.

### Complete explicit rendering examples by use case

Basic explicit implementation

Example

```

<!DOCTYPE html>

<html>

  <head>

    <title>Explicit Rendering</title>

    <script

      src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"

      defer

    ></script>

  </head>

  <body>

    <form id="login-form">

      <input type="text" name="username" placeholder="Username" />

      <input type="password" name="password" placeholder="Password" />

      <div id="turnstile-widget"></div>

      <button type="submit">Login</button>

    </form>


    <script>

      window.onload = function () {

        turnstile.render("#turnstile-widget", {

          sitekey: "<YOUR-SITE-KEY>",

          callback: function (token) {

            console.log("Turnstile token:", token);

            // Handle successful verification

          },

          "error-callback": function (errorCode) {

            console.error("Turnstile error:", errorCode);

          },

        });

      };

    </script>

  </body>

</html>


```

Using onload callback

Example

```

<script

  src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit&onload=onTurnstileLoad"

  defer

></script>

<div id="widget-container"></div>

<script>

  function onTurnstileLoad() {

    turnstile.render("#widget-container", {

      sitekey: "<YOUR-SITE-KEY>",

      theme: "light",

      callback: function (token) {

        console.log("Challenge completed:", token);

      },

    });

  }

</script>


```

Advanced SPA implementation

Example

```

<div id="dynamic-form-container"></div>


<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"></script>


<script>

  class TurnstileManager {

    constructor() {

      this.widgets = new Map();

    }

    createWidget(containerId, config) {

      // Wait for Turnstile to be ready

      turnstile.ready(() => {

        const widgetId = turnstile.render(containerId, {

          sitekey: config.sitekey,

          theme: config.theme || "auto",

          size: config.size || "normal",

          callback: (token) => {

            console.log(`Widget ${widgetId} completed:`, token);

            if (config.onSuccess) config.onSuccess(token, widgetId);

          },

          "error-callback": (error) => {

            console.error(`Widget ${widgetId} error:`, error);

            if (config.onError) config.onError(error, widgetId);

          },

        });


        this.widgets.set(containerId, widgetId);

        return widgetId;

      });

    }

    removeWidget(containerId) {

      const widgetId = this.widgets.get(containerId);

      if (widgetId) {

        turnstile.remove(widgetId);

        this.widgets.delete(containerId);

      }

    }

    resetWidget(containerId) {

      const widgetId = this.widgets.get(containerId);

      if (widgetId) {

        turnstile.reset(widgetId);

      }

    }

  }


  // Usage

  const manager = new TurnstileManager();


  // Create a widget when user clicks a button

  document.getElementById("show-form-btn").addEventListener("click", () => {

    document.getElementById("dynamic-form-container").innerHTML = `

        <form>

            <input type="email" placeholder="Email" />

            <div id="turnstile-widget"></div>

            <button type="submit">Submit</button>

        </form>

    `;

    manager.createWidget("#turnstile-widget", {

      sitekey: "<YOUR-SITE-KEY>",

      theme: "dark",

      onSuccess: (token) => {

        // Handle successful verification

        console.log("Form ready for submission");

      },

    });

  });

</script>


```

### Widget lifecycle management

Explicit rendering provides full control over the widget lifecycle.

JavaScript

```

// Render a widget

const widgetId = turnstile.render("#container", {

  sitekey: "<YOUR-SITE-KEY>",

  callback: handleSuccess,

});


// Get the current token

const token = turnstile.getResponse(widgetId);


// Check if widget is expired

const isExpired = turnstile.isExpired(widgetId);


// Reset the widget (clears current state)

turnstile.reset(widgetId);


// Remove the widget completely

turnstile.remove(widgetId);


```

### Execution mode

Control when challenges run with execution modes.

JavaScript

```

// Render widget but don't run challenge yet

const widgetId = turnstile.render("#container", {

  sitekey: "<YOUR-SITE-KEY>",

  execution: "execute", // Don't auto-execute

});


// Later, run the challenge when needed

turnstile.execute("#container");


```

---

## Performance and user experience optimization

Cloudflare recommends that you execute the Turnstile script as early upon the visitor's page entry as possible, so that the verification is complete and the interaction is available once the visitor attempts an action on the page.

---

## Configuration options

Both implicit and explicit rendering methods support the same configuration options. Refer to the table below for the most commonly used configurations.

| Option         | Description                | Values                            |
| -------------- | -------------------------- | --------------------------------- |
| sitekey        | Your widget's sitekey      | Required string                   |
| theme          | Visual theme               | auto, light, dark                 |
| size           | Widget size                | normal, flexible, compact         |
| callback       | Success callback           | Function                          |
| error-callback | Error callback             | Function                          |
| execution      | When to run the challenge  | render, execute                   |
| appearance     | When the widget is visible | always, execute, interaction-only |

For a complete list of configuration options, refer to [Widget configurations](https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/widget-configurations/).

---

## Testing

You can test your Turnstile widget on your webpage without triggering an actual Cloudflare Challenge by using a testing sitekey.

Refer to [Testing](https://developers.cloudflare.com/turnstile/troubleshooting/testing/) for more information.

---

## Limitations

Turnstile is designed to function only on pages using `http://` or `https://` URI schemes. Other protocols, such as `file://`, are not supported for embedding the widget.

---

## Security requirements

* Server-side validation is mandatory. It is critical to enforce Turnstile tokens with the Siteverify API. The Turnstile token could be invalid, expired, or already redeemed. Not verifying the token will leave major vulnerabilities in your implementation. You must call Siteverify to complete your Turnstile configuration. Otherwise, it is incomplete and will result in zeroes for token validation when viewing your metrics in [Turnstile Analytics](https://developers.cloudflare.com/turnstile/turnstile-analytics/).
* Tokens expire after 300 seconds (5 minutes). Each token can only be validated once. Expired or used tokens must be replaced with fresh challenges.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/get-started/","name":"Get started"}},{"@type":"ListItem","position":4,"item":{"@id":"/turnstile/get-started/client-side-rendering/","name":"Embed the widget"}}]}
```

---

---
title: Widget configurations
description: Configure widget appearance, language, and callback functions.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Widget configurations

Configure your Turnstile widget's appearance, behavior, and functionality using data attributes or JavaScript render parameters.

## Rendering methods

Turnstile widgets can be implemented using implicit or explicit rendering.

* [ Implicit rendering ](#tab-panel-10871)
* [ Explicit rendering ](#tab-panel-10872)

Implicit rendering automatically scans your HTML for elements with the `cf-turnstile` class and renders the widget when the page loads. It is best used for simple implementations, static websites, or when you want widgets to appear immediately on page load.

**How it works**

1. Add the Turnstile script to your page.
2. Include `<div class="cf-turnstile" data-sitekey="your-key"></div>` elements.
3. Widgets will render automatically when the page loads.
4. Configure the widget using `data-*` attributes on the HTML element.

Example

```

  <script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-theme="light"></div>


```

Explicit rendering gives you programmatic control over when and how widgets are created using JavaScript functions. It is best used for dynamic websites and single-page applications (SPAs), when you need to control timing of widget creation, conditional rendering based on visitor interactions, or for multiple widgets with different configurations.

**How it works**

1. Add the Turnstile script with `?render=explicit` parameter.
2. Create container elements (without the `cf-turnstile` class).
3. Call `turnstile.render()` function when you want to create widgets.
4. Configure the widget using JavaScript object parameters.

Example

```

  <script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit" defer></script>

  <div id="my-widget"></div>


  <script>

  window.onload = function() {

    turnstile.render('#my-widget', {

      sitekey: '<YOUR-SITE-KEY>',

      theme: 'light',

      callback: function(token) {

        console.log('Success:', token);

      }

    });

  };

  </script>


```

---

## Widget sizes

The Turnstile widget can have two different fixed sizes or a flexible width size when using the Managed or Non-Interactive modes.

| Size     | Width             | Height | Use case                  |
| -------- | ----------------- | ------ | ------------------------- |
| Normal   | 300px             | 65px   | Standard implementation   |
| Flexible | 100% (min: 300px) | 65px   | Responsive design         |
| Compact  | 150px             | 140px  | Space-constrained layouts |

* `normal`: The default size works well for most desktop and mobile layouts. Use this if you have adequate horizontal space on your website or form.
* `flexible`: Automatically adapts to the container width while maintaining minimum usability. Use this for responsive designs that need to work across all screen sizes.
* `compact`: Ideal for mobile interfaces, sidebars, or any space where horizontal space is limited. The compact widget is taller than normal to accommodate the smaller width.

Note

Widget size only applies to Managed and Non-Interactive modes. Invisible widgets have no visual footprint regardless of size configuration.

* [ Implicit rendering ](#tab-panel-10859)
* [ Explicit rendering ](#tab-panel-10860)

Normal size (default)

```

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>


```

Flexible size

```

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-size="flexible"></div>


```

Compact size

```

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-size="compact"></div>


```

Normal size (default)

```

  turnstile.render('#widget-container', {

    sitekey: '<YOUR-SITE-KEY>'

  });


```

Flexible size

```

  turnstile.render('#widget-container', {

    sitekey: '<YOUR-SITE-KEY>',

    size: 'flexible'

  });


```

Compact size

```

  turnstile.render('#widget-container', {

    sitekey: '<YOUR-SITE-KEY>',

    size: 'compact'

  });


```

---

## Theme options

Customize the widget's visual appearance to match your website's design.

* `auto` (default): Automatically matches the visitor's system theme preference. Auto is recommended for most implementations as it respects the visitor's preferences and provides the best accessibility experience.
* `light`: Light theme with bright colors and clear contrast. Light theme works best on bright backgrounds and provides high contrast for readability.
* `dark`: Dark theme optimized for dark interfaces. Dark theme is ideal for dark interfaces, gaming sites, or applications with dark color schemes.

* [ Implicit rendering ](#tab-panel-10861)
* [ Explicit rendering ](#tab-panel-10862)

Auto theme (default)

```

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>


```

Light theme

```

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-theme="light"></div>


```

Dark theme

```

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-theme="dark"></div>


```

Auto theme (default)

```

  turnstile.render('#widget-container', {

    sitekey: '<YOUR-SITE-KEY>'

  });


```

Light theme

```

  turnstile.render('#widget-container', {

    sitekey: '<YOUR-SITE-KEY>',

    theme: 'light'

  });


```

Dark theme

```

  turnstile.render('#widget-container', {

    sitekey: '<YOUR-SITE-KEY>',

    theme: 'dark'

  });


```

---

## Appearance modes

Control when the widget becomes visible to visitors using the appearance mode.

* `always` (default): The widget is always visible from page load. This is the best option for most implementations where you want your visitors to see the widget immediately as it provides clear visual feedback that security verification is in place.
* `execute`: The widget only becomes visible after the challenge begins. This is useful for when you need to control the timing of widget appearance, such as showing it only when a visitor starts filling out a form or selecting a submit button.
* `interaction-only`: The widget becomes visible only when visitor interaction is required and provides the cleanest visitor experience. Most visitors will never see the widget, but suspected bots will encounter the interactive challenge.

Note

Appearance modes only affect visible widget types (Managed and Non-Interactive). Invisible widgets are never shown regardless of the appearance setting.

* [ Implicit rendering ](#tab-panel-10863)
* [ Explicit rendering ](#tab-panel-10864)

Always visible (default)

```

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>


```

Visible only after challenge begins

```

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-appearance="execute"></div>


```

Visible only when interaction is needed

```

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-appearance="interaction-only"></div>


```

Always visible (default)

```

  turnstile.render('#widget-container', {

    sitekey: '<YOUR-SITE-KEY>'

  });


```

Visible only after challenge begins

```

  turnstile.render('#widget-container', {

    sitekey: '<YOUR-SITE-KEY>',

    appearance: 'execute'

  });


```

Visible only when interaction is needed

```

  turnstile.render('#widget-container', {

    sitekey: '<YOUR-SITE-KEY>',

    appearance: 'interaction-only'

  });


```

---

## Execution modes

Control when the challenge runs and a token is generated.

* `render` (default): The challenge runs automatically after calling the `render()` function and provides immediate protection as soon as the widget loads. The challenge runs in the background while the page loads, ensuring the token is ready when the visitor submits data.
* `execute`: The challenge runs after calling the `turnstile.execute()` function separately and gives you precise control over when verification occurs. This option is useful for multi-step forms, conditional verification, or when you want to defer the challenge until the visitor actually attempts to submit data. This can improve page load performance and visitor experience by only running verification when needed.  
**Common scenarios**  
   * Multi-step forms: Run verification only on the final step.  
   * Conditional protection: Only verify visitors who meet certain criteria.  
   * Performance optimization: Defer verification to reduce initial page load time.  
   * User-triggered verification: Let visitors manually start the verification process.

* [ Implicit rendering ](#tab-panel-10865)
* [ Explicit rendering ](#tab-panel-10866)

Auto execution (default)

```

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>


```

Manual execution

```

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-execution="execute"></div>


```

Auto execution (default)

```

  turnstile.render('#widget-container', {

    sitekey: '<YOUR-SITE-KEY>'

  });


```

Manual execution

```

  turnstile.render('#widget-container', {

    sitekey: '<YOUR-SITE-KEY>',

    execution: 'execute'

  });


```

Execute the challenge later

```

  turnstile.execute('#widget-container');


```

---

## Language configuration

Set the language for the widget interface.

* `auto` (default): Uses the visitor's browser language preference.
* Specific language codes: ISO 639-1 two-letter codes, such as `es`, `fr`, `de`.
* Language and region: Combined codes for regional variants, such as `en-US`, `es-MX`, `pt-BR`.

Notes

* When set to `auto`, Turnstile automatically detects the visitor's preferred language from their browser settings.
* If a requested language is not supported, Turnstile falls back to English.
* Language affects all visitor-facing text including loading messages, error states, and accessibility labels.
* Setting specific languages can improve visitor experience for international audiences.

* [ Implicit rendering ](#tab-panel-10867)
* [ Explicit rendering ](#tab-panel-10868)

Auto language (default)

```

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>


```

Specific language

```

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-language="es"></div>


```

Language and country

```

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-language="en-US"></div>


```

Auto language (default)

```

  turnstile.render('#widget-container', {

    sitekey: '<YOUR-SITE-KEY>'

  });


```

Specific language

```

  turnstile.render('#widget-container', {

    sitekey: '<YOUR-SITE-KEY>',

    language: 'es'

  });


```

---

## Callback configuration

Handle widget events with callbacks.

* `callback`: Triggered when the challenge is successfully completed.
* `error-callback`: Triggered when an error occurs during the challenge.
* `expired-callback`: Triggered when a token expires (before timeout).
* `timeout-callback`: Triggered when an interactive challenge times out.

The success callback receives a token that must be validated on your server using the Siteverify API. Tokens are single-use and expire after 300 seconds (five minutes).

* [ Implicit rendering ](#tab-panel-10869)
* [ Explicit rendering ](#tab-panel-10870)

```

  <div class="cf-turnstile"

    data-sitekey="<YOUR-SITE-KEY>"

    data-callback="onSuccess"

    data-error-callback="onError"

    data-expired-callback="onExpired"

    data-timeout-callback="onTimeout"></div>

  <script>

  function onSuccess(token) {

  console.log('Challenge Success:', token);

  }

  function onError(errorCode) {

  console.log('Challenge Error:', errorCode);

  }

  function onExpired() {

  console.log('Token expired');

  }

  function onTimeout() {

  console.log('Challenge timed out');

  }

  </script>


```

JavaScript

```

  turnstile.render('#widget-container', {

    sitekey: '<YOUR-SITE-KEY>',

    callback: function(token) {

      console.log('Challenge Success:', token);

    },

    'error-callback': function(errorCode) {

      console.log('Challenge Error:', errorCode);

    },

    'expired-callback': function() {

      console.log('Token expired');

    },

    'timeout-callback': function() {

      console.log('Challenge timed out');

    }

  });


```

### Best practices

* Always implement the success callback to handle the token and proceed with form submission or next steps.
* Use error callbacks for graceful error handling and visitor feedback.
* Monitor expired tokens to refresh challenges before they become invalid.
* Handle timeouts to guide visitors through challenge resolution.

---

## Advanced configuration options

### Retry behavior

Control how Turnstile handles failed challenges.

* `auto` (default): Automatically retries failed challenges. Auto retry provides better visitor experience by automatically recovering from temporary network issues or processing errors.
* `never`: Disables automatic retry. This requires manual intervention and gives you full control over error handling in applications that need custom retry logic.
* `retry-interval`: Controls the time between retry attempts (default: 8000ms) and lets you balance between quick recovery and server load.

Auto retry (default)

```

<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>


```

Disable retry

```

<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-retry="never"></div>


```

Custom retry interval (8000ms default)

```

<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-retry-interval="0000"></div>


```

### Refresh behavior

Control how Turnstile handles token expiration and interactive timeouts.

* `refresh-expired`: Controls behavior when tokens expire (`auto`, `manual`, `never`).
* `refresh-timeout`: Controls behavior when interactive challenges timeout (`auto`, `manual`, `never`).

#### Benefits

* `auto` refresh provides seamless visitor experience but uses more resources.
* `manual` refresh gives visitors control but requires them to take action.
* `never` refresh requires your application to handle all refresh logic.

Different strategies can be used for token expiration versus interactive timeouts based on your visitor experience requirements.

Auto refresh expired tokens (default)

```

<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>


```

Manual refresh

```

<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-refresh-expired="manual"></div>


```

Auto refresh timeouts (default for Managed mode)

```

<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-refresh-timeout="auto"></div>


```

### Custom data

Add custom identifiers and data to your challenges.

* `action`: A custom identifier for analytics and differentiation (maximum 32 characters).
* `cData`: Custom payload data returned during validation (maximum 255 characters).

#### Use cases

* Action tracking: Differentiate between login, signup, contact forms, and more. in your analytics.
* Visitor context: Pass visitor IDs, session information, or other contextual data.
* A/B testing: Track different widget configurations or page variants.
* Fraud detection: Include additional context for risk assessment.

Warning

Both action and cData fields only accept alphanumeric characters, underscores (\_), and hyphens (-).

Add custom action identifier

```

<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-action="login"></div>


```

Add custom data payload

```

<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-cdata="user-cdata"></div>


```

### Form integration

Configure how Turnstile integrates with HTML forms.

When enabled, Turnstile automatically creates a hidden `<input>` element with the verification token. This gets submitted along with your other form data, making server-side validation straightforward.

* `response-field`: Determines whether to create a hidden form field with the token (`default: true`)
* `response-field-name`: Custom name for the hidden form field (`default: cf-turnstile-response`)

#### Benefits

* Automatic form integration means that the token is included when the form is submitted, requiring no additional JavaScript.
* Custom field names helps avoid conflicts with existing form fields.
* Disabled response fields give you full control over token handling for complex form scenarios.

Custom response field name

```

<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-response-field-name="turnstile-token"></div>


```

Disable response field

```

<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>" data-response-field="false"></div>


```

---

## Complete configuration reference

| JavaScript Render Parameters | Data Attribute                   | Description                                                                                                                                                                                                                                                                                                                                            |
| ---------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| sitekey                      | data-sitekey                     | Every widget has a sitekey. This sitekey is associated with the corresponding widget configuration and is created upon the widget creation.                                                                                                                                                                                                            |
| action                       | data-action                      | A customer value that can be used to differentiate widgets under the same sitekey in analytics and which is returned upon validation. This can only contain up to 32 alphanumeric characters including \_ and \-.                                                                                                                                      |
| cData                        | data-cdata                       | A customer payload that can be used to attach customer data to the challenge throughout its issuance and which is returned upon validation. This can only contain up to 255 alphanumeric characters including \_ and \-.                                                                                                                               |
| callback                     | data-callback                    | A JavaScript callback invoked upon success of the challenge. The callback is passed a token that can be validated.                                                                                                                                                                                                                                     |
| error-callback               | data-error-callback              | A JavaScript callback invoked when there is an error (e.g. network error or the challenge failed). Refer to [Client-side errors](https://developers.cloudflare.com/turnstile/troubleshooting/client-side-errors/).                                                                                                                                     |
| execution                    | data-execution                   | Execution controls when to obtain the token of the widget and can be on render (default) or on execute. Refer to [Execution Modes](https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/#execution-modes) for more information.                                                                                               |
| expired-callback             | data-expired-callback            | A JavaScript callback invoked when the token expires and does not reset the widget.                                                                                                                                                                                                                                                                    |
| before-interactive-callback  | data-before-interactive-callback | A JavaScript callback invoked before the challenge enters interactive mode.                                                                                                                                                                                                                                                                            |
| after-interactive-callback   | data-after-interactive-callback  | A JavaScript callback invoked when challenge has left interactive mode.                                                                                                                                                                                                                                                                                |
| unsupported-callback         | data-unsupported-callback        | A JavaScript callback invoked when a given client/browser is not supported by Turnstile.                                                                                                                                                                                                                                                               |
| theme                        | data-theme                       | The widget theme. Can take the following values: light, dark, auto. The default is auto, which respects the visitor preference. This can be forced to light or dark by setting the theme accordingly.                                                                                                                                                  |
| language                     | data-language                    | Language to display, must be either: auto (default) to use the language that the visitor has chosen, or an ISO 639-1 two-letter language code (e.g. en) or language and country code (e.g. en-US). Refer to the [list of supported languages](https://developers.cloudflare.com/turnstile/reference/supported-languages/) for more information.        |
| tabindex                     | data-tabindex                    | The tabindex of Turnstile's iframe for accessibility purposes. The default value is 0.                                                                                                                                                                                                                                                                 |
| timeout-callback             | data-timeout-callback            | A JavaScript callback invoked when the challenge presents an interactive challenge but was not solved within a given time. A callback will reset the widget to allow a visitor to solve the challenge again.                                                                                                                                           |
| response-field               | data-response-field              | A boolean that controls if an input element with the response token is created, defaults to true.                                                                                                                                                                                                                                                      |
| response-field-name          | data-response-field-name         | Name of the input element, defaults to cf-turnstile-response.                                                                                                                                                                                                                                                                                          |
| size                         | data-size                        | The widget size. Can take the following values: normal, flexible, compact.                                                                                                                                                                                                                                                                             |
| retry                        | data-retry                       | Controls whether the widget should automatically retry to obtain a token if it did not succeed. The default is auto, which will retry automatically. This can be set to never to disable retry on failure.                                                                                                                                             |
| retry-interval               | data-retry-interval              | When retry is set to auto, retry-interval controls the time between retry attempts in milliseconds. Value must be a positive integer less than 900000, defaults to 8000.                                                                                                                                                                               |
| refresh-expired              | data-refresh-expired             | Automatically refreshes the token when it expires. Can take auto, manual, or never, defaults to auto.                                                                                                                                                                                                                                                  |
| refresh-timeout              | data-refresh-timeout             | Controls whether the widget should automatically refresh upon entering an interactive challenge and observing a timeout. Can take auto (automatically refreshes upon encountering an interactive timeout), manual (prompts the visitor to manually refresh) or never (will show a timeout), defaults to auto. Only applies to widgets of Managed mode. |
| appearance                   | data-appearance                  | Appearance controls when the widget is visible. It can be always (default), execute, or interaction-only. Refer to [Appearance modes](https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/#appearance-modes) for more information.                                                                                           |
| feedback-enabled             | data-feedback-enabled            | Allows Cloudflare to gather visitor feedback upon widget failure. It can be true (default) or false.                                                                                                                                                                                                                                                   |
| offlabel-show-privacy        | data-offlabel-show-privacy       | Displays privacy link for unbranded Turnstile widgets. Can be true (default) or false.                                                                                                                                                                                                                                                                 |
| offlabel-show-help           | data-offlabel-show-help          | Displays help link for unbranded Turnstile widgets. Can be true (default) or false.                                                                                                                                                                                                                                                                    |

### Examples

Responsive design widget

```

<div style="max-width: 500px;">

  <div class="cf-turnstile" data-sitekey=<YOUR-SITE-KEY> data-size="flexible" data-theme="auto"></div>

</div>


```

Mobile-optimized compact widget

```

<div class="cf-turnstile" data-sitekey=<YOUR-SITE-KEY> data-size="compact" data-theme="light" data-language="en">

</div>


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/get-started/","name":"Get started"}},{"@type":"ListItem","position":4,"item":{"@id":"/turnstile/get-started/client-side-rendering/","name":"Embed the widget"}},{"@type":"ListItem","position":5,"item":{"@id":"/turnstile/get-started/client-side-rendering/widget-configurations/","name":"Widget configurations"}}]}
```

---

---
title: Mobile implementation
description: Implement Turnstile in native mobile applications.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Mobile implementation

Turnstile requires a browser environment because it runs JavaScript challenges in the visitor's browser. On mobile devices, Turnstile works in mobile browsers without additional configuration.

For native mobile applications, Turnstile does not run natively. Instead, you use a WebView — a browser component embedded inside your native app — to load a webpage that contains the Turnstile widget.

---

## WebView integration

A WebView embeds a browser engine within your native application, enabling you to show web pages, forms, and JavaScript-powered content like Turnstile widgets.

### Requirements

For Turnstile to function properly in WebView, the following requirements must be met.

#### JavaScript support

* JavaScript execution must be enabled.
* DOM storage API must be available.
* Standard web APIs must be accessible.

#### Network access

* Access to `challenges.cloudflare.com`
* Support for both HTTP and HTTPS connections.
* Allow connections to `about:blank` and `about:srcdoc`

#### Environment consistency

* Consistent User Agent throughout the session
* Stable device and browser characteristics
* No modification to core browser behavior

### Platform-specific implementation

#### Android WebView

```

WebView webView = findViewById(R.id.webview);

WebSettings webSettings = webView.getSettings();


// Required: Enable JavaScript

webSettings.setJavaScriptEnabled(true);


// Required: Enable DOM storage

webSettings.setDomStorageEnabled(true);


// Recommended: Enable other web features

webSettings.setLoadWithOverviewMode(true);

webSettings.setUseWideViewPort(true);

webSettings.setAllowFileAccess(true);

webSettings.setAllowContentAccess(true);


// Load your web content with Turnstile

webView.loadUrl("https://yoursite.com/protected-form");


```

#### iOS WKWebView (Swift)

Swift

```

import WebKit


class ViewController: UIViewController {

    @IBOutlet weak var webView: WKWebView!


    override func viewDidLoad() {

        super.viewDidLoad()


        // Configure WebView

        let configuration = WKWebViewConfiguration()

        configuration.preferences.javaScriptEnabled = true


        // Load your web content with Turnstile

        if let url = URL(string: "https://yoursite.com/protected-form") {

            webView.load(URLRequest(url: url))

        }

    }

}


```

#### React Native WebView

JavaScript

```

import { WebView } from "react-native-webview";


export default function App() {

  return (

    <WebView

      source={{ uri: "https://yoursite.com/protected-form" }}

      javaScriptEnabled={true}

      domStorageEnabled={true}

      allowsInlineMediaPlayback={true}

      mediaPlaybackRequiresUserAction={false}

    />

  );

}


```

#### Flutter WebView

Dart

```

import 'package:flutter_inappwebview/flutter_inappwebview.dart';


class WebViewScreen extends StatelessWidget {

  @override

  Widget build(BuildContext context) {

    return InAppWebView(

      initialUrlRequest: URLRequest(

        url: Uri.parse('https://yoursite.com/protected-form')

      ),

      initialOptions: InAppWebViewGroupOptions(

        crossPlatform: InAppWebViewOptions(

          javaScriptEnabled: true,

          useShouldOverrideUrlLoading: false,

        ),

        android: AndroidInAppWebViewOptions(

          domStorageEnabled: true,

        ),

        ios: IOSInAppWebViewOptions(

          allowsInlineMediaPlayback: true,

        ),

      ),

    );

  }

}


```

---

## Common implementation issues

### User Agent consistency

Changing the User Agent during a session causes Turnstile challenges to fail because the system relies on consistent browser characteristics to validate the visitor's authenticity. When the User Agent changes mid-session, Turnstile treats this as a potential security risk and rejects the challenge.

```

// Android - Set consistent User Agent

webSettings.setUserAgentString(webSettings.getUserAgentString());


```

Swift

```

// iOS - Maintain default User Agent

webView.customUserAgent = webView.value(forKey: "userAgent") as? String


```

### Content Security Policy (CSP)

Strict [Content Security Policy](https://developers.cloudflare.com/turnstile/reference/content-security-policy/) settings can prevent Turnstile from loading the necessary scripts and making required network connections. This happens when CSP headers or meta tags block access to the domains and resources that Turnstile needs to function properly.

```

<meta

  http-equiv="Content-Security-Policy"

  content="

  default-src 'self';

  script-src 'self' challenges.cloudflare.com 'unsafe-inline';

  connect-src 'self' challenges.cloudflare.com;

  frame-src 'self' challenges.cloudflare.com;

"

/>


```

### Domain configuration

WebView security restrictions can prevent access to the domains that Turnstile requires for proper operation. Some WebViews are configured to only allow specific domains or block certain types of connections, which can interfere with Turnstile's ability to load challenges and communicate with Cloudflare's servers.

To resolve this, configure your WebView's allowed origins to include all domains that Turnstile needs:

* `challenges.cloudflare.com`
* `about:blank`
* `about:srcdoc`
* Your own domain(s)

The exact configuration method varies by platform, but the principle is to explicitly allow network access for these domains.

### Cookie and storage issues

Cookies and local storage not persisting between sessions can cause Turnstile to fail because it relies on these mechanisms to maintain state and track visitor behavior. This commonly occurs when WebView storage settings are too restrictive or when the app clears storage between sessions. Ensure that your WebView is configured to properly handle cookies and local storage.

```

// Android - Enable cookies

CookieManager.getInstance().setAcceptCookie(true);

CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);


```

Swift

```

// iOS - Configure cookie storage

webView.configuration.websiteDataStore = WKWebsiteDataStore.default()


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/get-started/","name":"Get started"}},{"@type":"ListItem","position":4,"item":{"@id":"/turnstile/get-started/mobile-implementation/","name":"Mobile implementation"}}]}
```

---

---
title: Validate the token
description: Validate Turnstile tokens on your server with the siteverify API.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Validate the token

Learn how to securely validate Turnstile tokens on your server using the Siteverify API.

Mandatory server-side validation

You must call the Siteverify API to complete your Turnstile implementation. The client-side widget alone does not protect your forms.

Server-side validation is required because:

* **Tokens can be forged.** An attacker can submit any string to your form endpoint without completing a challenge.
* **Tokens expire.** Each token is valid for 300 seconds (5 minutes) after generation.
* **Tokens are single-use.** Each token can only be validated once. A replayed token will be rejected with the `timeout-or-duplicate` error code.

## Process

1. Client generates token: Visitor completes Turnstile challenge on your webpage.
2. Token sent to server: Form submission includes the Turnstile token.
3. Server validates token: Your server calls Cloudflare's Siteverify API.
4. Cloudflare responds: Returns `success` or `failure` and additional data.
5. Server takes action: Allow or reject the original request based on validation.

## Siteverify API overview

Endpoint

```

POST https://challenges.cloudflare.com/turnstile/v0/siteverify


```

### Request format

The API accepts both `application/x-www-form-urlencoded` and `application/json` requests, but always returns JSON responses.

#### Required parameters

| Parameter        | Required | Description                                             |
| ---------------- | -------- | ------------------------------------------------------- |
| secret           | Yes      | Your widget's secret key from the Cloudflare dashboard  |
| response         | Yes      | The token from the client-side widget                   |
| remoteip         | No       | The visitor's IP address                                |
| idempotency\_key | No       | A UUID you generate to safely retry validation requests |

#### Token characteristics

* Maximum length: 2048 characters
* Validity period: 300 seconds (5 minutes) from generation
* Single use: Each token can only be validated once
* Automatic expiry: Tokens automatically expire and cannot be reused

The validation token issued by Turnstile is valid for five minutes. If a user submits the form after this period, the token is considered expired. In this scenario, the server-side verification API will return a failure, and the `error-codes` field in the response will include `timeout-or-duplicate`.

To ensure a successful validation, the visitor must initiate the request and submit the token to your backend within the five-minute window. Otherwise, the Turnstile widget needs to be refreshed to generate a new token. This can be done using the `turnstile.reset` function.

---

## Basic validation examples

* [  JavaScript ](#tab-panel-10873)
* [  PHP ](#tab-panel-10874)
* [  Python ](#tab-panel-10875)
* [  Java ](#tab-panel-10876)
* [  C# ](#tab-panel-10877)

#### JSON

JavaScript

```

const SECRET_KEY = "your-secret-key";


async function validateTurnstile(token, remoteip) {

  try {

    const response = await fetch(

      "https://challenges.cloudflare.com/turnstile/v0/siteverify",

      {

        method: "POST",

        headers: {

          "Content-Type": "application/json",

        },

        body: JSON.stringify({

          secret: SECRET_KEY,

          response: token,

          remoteip: remoteip,

        }),

      },

    );


    const result = await response.json();

    return result;

  } catch (error) {

    console.error("Turnstile validation error:", error);

    return { success: false, "error-codes": ["internal-error"] };

  }

}


```

#### Form Data

JavaScript

```

const SECRET_KEY = "your-secret-key";


async function validateTurnstile(token, remoteip) {

  const formData = new FormData();

  formData.append("secret", SECRET_KEY);

  formData.append("response", token);

  formData.append("remoteip", remoteip);


  try {

    const response = await fetch(

      "https://challenges.cloudflare.com/turnstile/v0/siteverify",

      {

        method: "POST",

        body: formData,

      },

    );


    const result = await response.json();

    return result;

  } catch (error) {

    console.error("Turnstile validation error:", error);

    return { success: false, "error-codes": ["internal-error"] };

  }

}


// Usage in form handler

async function handleFormSubmission(request) {

  const body = await request.formData();

  const token = body.get("cf-turnstile-response");

  const ip =

    request.headers.get("CF-Connecting-IP") ||

    request.headers.get("X-Forwarded-For") ||

    "unknown";


  const validation = await validateTurnstile(token, ip);


  if (validation.success) {

    // Token is valid - process the form

    console.log("Valid submission from:", validation.hostname);

    return processForm(body);

  } else {

    // Token is invalid - reject the submission

    console.log("Invalid token:", validation["error-codes"]);

    return new Response("Invalid verification", { status: 400 });

  }

}


```

```

<?php

function validateTurnstile($token, $secret, $remoteip = null) {

    $url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';


    $data = [

        'secret' => $secret,

        'response' => $token

    ];


    if ($remoteip) {

        $data['remoteip'] = $remoteip;

    }


    $options = [

        'http' => [

            'header' => "Content-type: application/x-www-form-urlencoded\r\n",

            'method' => 'POST',

            'content' => http_build_query($data)

        ]

    ];


    $context = stream_context_create($options);

    $response = file_get_contents($url, false, $context);


    if ($response === FALSE) {

        return ['success' => false, 'error-codes' => ['internal-error']];

    }


    return json_decode($response, true);


}


// Usage

$secret_key = 'your-secret-key';

$token = $_POST['cf-turnstile-response'] ?? '';

$remoteip = $\_SERVER['HTTP_CF_CONNECTING_IP'] ??

$\_SERVER['HTTP_X_FORWARDED_FOR'] ??

$\_SERVER['REMOTE_ADDR'];


$validation = validateTurnstile($token, $secret_key, $remoteip);


if ($validation['success']) {

// Valid token - process form

echo "Form submission successful!";

// Process your form data here

} else {

// Invalid token - show error

echo "Verification failed. Please try again.";

error_log('Turnstile validation failed: ' . implode(', ', $validation['error-codes']));

}

?>


```

Python

```

import requests


def validate_turnstile(token, secret, remoteip=None):

    url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'


    data = {

        'secret': secret,

        'response': token

    }


    if remoteip:

        data['remoteip'] = remoteip


    try:

        response = requests.post(url, data=data, timeout=10)

        response.raise_for_status()

        return response.json()

    except requests.RequestException as e:

        print(f"Turnstile validation error: {e}")

        return {'success': False, 'error-codes': ['internal-error']}


# Usage with Flask

from flask import Flask, request, jsonify


app = Flask(__name__)

SECRET_KEY = 'your-secret-key'


@app.route('/submit-form', methods=['POST'])

def submit_form():

    token = request.form.get('cf-turnstile-response')

    remoteip = request.headers.get('CF-Connecting-IP') or \

               request.headers.get('X-Forwarded-For') or \

               request.remote_addr


    validation = validate_turnstile(token, SECRET_KEY, remoteip)


    if validation['success']:

        # Valid token - process form

        return jsonify({'status': 'success', 'message': 'Form submitted successfully'})

    else:

        # Invalid token - reject submission

        return jsonify({

            'status': 'error',

            'message': 'Verification failed',

            'errors': validation['error-codes']

        }), 400


```

```

import org.springframework.web.client.RestTemplate;

import org.springframework.util.LinkedMultiValueMap;

import org.springframework.util.MultiValueMap;

import org.springframework.http.HttpEntity;

import org.springframework.http.HttpHeaders;

import org.springframework.http.MediaType;

import org.springframework.http.ResponseEntity;


@Service

public class TurnstileService {

private static final String SITEVERIFY_URL = "https://challenges.cloudflare.com/turnstile/v0/siteverify";

private final String secretKey = "your-secret-key";

private final RestTemplate restTemplate = new RestTemplate();


    public TurnstileResponse validateToken(String token, String remoteip) {

        HttpHeaders headers = new HttpHeaders();

        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);


        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();

        params.add("secret", secretKey);

        params.add("response", token);

        if (remoteip != null) {

            params.add("remoteip", remoteip);

        }


        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, headers);


        try {

            ResponseEntity<TurnstileResponse> response = restTemplate.postForEntity(

                SITEVERIFY_URL, request, TurnstileResponse.class);

            return response.getBody();

        } catch (Exception e) {

            TurnstileResponse errorResponse = new TurnstileResponse();

            errorResponse.setSuccess(false);

            errorResponse.setErrorCodes(List.of("internal-error"));

            return errorResponse;

        }

    }


}


// Controller usage

@PostMapping("/submit-form")

public ResponseEntity<?> submitForm(

@RequestParam("cf-turnstile-response") String token,

HttpServletRequest request) {


    String remoteip = request.getHeader("CF-Connecting-IP");

    if (remoteip == null) {

        remoteip = request.getHeader("X-Forwarded-For");

    }

    if (remoteip == null) {

        remoteip = request.getRemoteAddr();

    }


    TurnstileResponse validation = turnstileService.validateToken(token, remoteip);


    if (validation.isSuccess()) {

        // Valid token - process form

        return ResponseEntity.ok("Form submitted successfully");

    } else {

        // Invalid token - reject submission

        return ResponseEntity.badRequest()

            .body("Verification failed: " + validation.getErrorCodes());

    }


}


```

```

using System.Text.Json;


public class TurnstileService

{

    private readonly HttpClient _httpClient;

    private readonly string _secretKey = "your-secret-key";

    private const string SiteverifyUrl = "https://challenges.cloudflare.com/turnstile/v0/siteverify";


    public TurnstileService(HttpClient httpClient)

    {

        _httpClient = httpClient;

    }


    public async Task<TurnstileResponse> ValidateTokenAsync(string token, string remoteip = null)

    {

        var parameters = new Dictionary<string, string>

        {

            { "secret", _secretKey },

            { "response", token }

        };


        if (!string.IsNullOrEmpty(remoteip))

        {

            parameters.Add("remoteip", remoteip);

        }


        var postContent = new FormUrlEncodedContent(parameters);


        try

        {

            var response = await _httpClient.PostAsync(SiteverifyUrl, postContent);

            var stringContent = await response.Content.ReadAsStringAsync();


            return JsonSerializer.Deserialize<TurnstileResponse>(stringContent);

        }

        catch (Exception ex)

        {

            return new TurnstileResponse

            {

                Success = false,

                ErrorCodes = new[] { "internal-error" }

            };

        }

    }

}


// Controller usage

[HttpPost("submit-form")]

public async Task<IActionResult> SubmitForm([FromForm] string cfTurnstileResponse)

{

    var remoteip = HttpContext.Request.Headers["CF-Connecting-IP"].FirstOrDefault() ??

                   HttpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault() ??

                   HttpContext.Connection.RemoteIpAddress?.ToString();


    var validation = await _turnstileService.ValidateTokenAsync(cfTurnstileResponse, remoteip);


    if (validation.Success)

    {

        // Valid token - process form

        return Ok("Form submitted successfully");

    }

    else

    {

        // Invalid token - reject submission

        return BadRequest($"Verification failed: {string.Join(", ", validation.ErrorCodes)}");

    }

}


```

---

## Advanced validation techniques

Idempotency keys for retry operation

```

const crypto = require("crypto");


async function validateWithRetry(token, remoteip, maxRetries = 3) {

  const idempotencyKey = crypto.randomUUID();


  for (let attempt = 1; attempt <= maxRetries; attempt++) {

    try {

      const formData = new FormData();

      formData.append("secret", SECRET_KEY);

      formData.append("response", token);

      formData.append("remoteip", remoteip);

      formData.append("idempotency_key", idempotencyKey);


      const response = await fetch(

        "https://challenges.cloudflare.com/turnstile/v0/siteverify",

        {

          method: "POST",

          body: formData,

        },

      );


      const result = await response.json();


      if (response.ok) {

        return result;

      }


      // If this is the last attempt, return the error

      if (attempt === maxRetries) {

        return result;

      }


      // Wait before retrying (exponential backoff)

      await new Promise((resolve) =>

        setTimeout(resolve, Math.pow(2, attempt) * 1000),

      );

    } catch (error) {

      if (attempt === maxRetries) {

        return { success: false, "error-codes": ["internal-error"] };

      }

    }

  }

}


```

Enhanced validation with custom checks

```

async function validateTurnstileEnhanced(

  token,

  remoteip,

  expectedAction = null,

  expectedHostname = null,

) {

  const validation = await validateTurnstile(token, remoteip);


  if (!validation.success) {

    return {

      valid: false,

      reason: "turnstile_failed",

      errors: validation["error-codes"],

    };

  }


  // Check if action matches expected value (if specified)

  if (expectedAction && validation.action !== expectedAction) {

    return {

      valid: false,

      reason: "action_mismatch",

      expected: expectedAction,

      received: validation.action,

    };

  }


  // Check if hostname matches expected value (if specified)

  if (expectedHostname && validation.hostname !== expectedHostname) {

    return {

      valid: false,

      reason: "hostname_mismatch",

      expected: expectedHostname,

      received: validation.hostname,

    };

  }


  // Check token age (warn if older than 4 minutes)

  const challengeTime = new Date(validation.challenge_ts);

  const now = new Date();

  const ageMinutes = (now - challengeTime) / (1000 * 60);


  if (ageMinutes > 4) {

    console.warn(`Token is ${ageMinutes.toFixed(1)} minutes old`);

  }


  return {

    valid: true,

    data: validation,

    tokenAge: ageMinutes,

  };

}


// Usage

const result = await validateTurnstileEnhanced(

  token,

  remoteip,

  "login", // expected action

  "example.com", // expected hostname

);


if (result.valid) {

  // Process the request

  console.log("Validation successful:", result.data);

} else {

  // Handle validation failure

  console.log("Validation failed:", result.reason);

}


```

---

## API response format

* [ Successful response ](#tab-panel-10878)
* [ Failed response ](#tab-panel-10879)

Example

```

{

  "success": true,

  "challenge_ts": "2022-02-28T15:14:30.096Z",

  "hostname": "example.com",

  "error-codes": [],

  "action": "login",

  "cdata": "sessionid-123456789",

  "metadata": {

    "ephemeral_id": "x:9f78e0ed210960d7693b167e"

  }

}


```

Example

```

{

  "success": false,

  "error-codes": ["invalid-input-response"]

}


```

### Response fields

| Field                  | Description                                      |
| ---------------------- | ------------------------------------------------ |
| success                | Boolean indicating if validation was successful  |
| challenge\_ts          | ISO 8601 timestamp when the challenge was solved |
| hostname               | Hostname where the challenge was served          |
| error-codes            | Array of error codes (if validation failed)      |
| action                 | Custom action identifier from client-side        |
| cdata                  | Custom data payload from client-side             |
| metadata.ephemeral\_id | Device fingerprint ID (Enterprise only)          |

### Error codes reference

| Error code             | Description                             | Action required                                   |
| ---------------------- | --------------------------------------- | ------------------------------------------------- |
| missing-input-secret   | Secret parameter not provided           | Ensure secret key is included                     |
| invalid-input-secret   | Secret key is invalid or expired        | Check your secret key in the Cloudflare dashboard |
| missing-input-response | Response parameter was not provided     | Ensure token is included                          |
| invalid-input-response | Token is invalid, malformed, or expired | User should retry the challenge                   |
| bad-request            | Request is malformed                    | Check request format and parameters               |
| timeout-or-duplicate   | Token has already been validated        | Each token can only be used once                  |
| internal-error         | Internal error occurred                 | Retry the request                                 |

---

## Implementation

Example implementation

```

class TurnstileValidator {

  constructor(secretKey, timeout = 10000) {

    this.secretKey = secretKey;

    this.timeout = timeout;

  }


  async validate(token, remoteip, options = {}) {

    // Input validation

    if (!token || typeof token !== "string") {

      return { success: false, error: "Invalid token format" };

    }


    if (token.length > 2048) {

      return { success: false, error: "Token too long" };

    }


    // Prepare request

    const controller = new AbortController();

    const timeoutId = setTimeout(() => controller.abort(), this.timeout);


    try {

      const formData = new FormData();

      formData.append("secret", this.secretKey);

      formData.append("response", token);


      if (remoteip) {

        formData.append("remoteip", remoteip);

      }


      if (options.idempotencyKey) {

        formData.append("idempotency_key", options.idempotencyKey);

      }


      const response = await fetch(

        "https://challenges.cloudflare.com/turnstile/v0/siteverify",

        {

          method: "POST",

          body: formData,

          signal: controller.signal,

        },

      );


      const result = await response.json();


      // Additional validation

      if (result.success) {

        if (

          options.expectedAction &&

          result.action !== options.expectedAction

        ) {

          return {

            success: false,

            error: "Action mismatch",

            expected: options.expectedAction,

            received: result.action,

          };

        }


        if (

          options.expectedHostname &&

          result.hostname !== options.expectedHostname

        ) {

          return {

            success: false,

            error: "Hostname mismatch",

            expected: options.expectedHostname,

            received: result.hostname,

          };

        }

      }


      return result;

    } catch (error) {

      if (error.name === "AbortError") {

        return { success: false, error: "Validation timeout" };

      }


      console.error("Turnstile validation error:", error);

      return { success: false, error: "Internal error" };

    } finally {

      clearTimeout(timeoutId);

    }

  }

}


// Usage

const validator = new TurnstileValidator(process.env.TURNSTILE_SECRET_KEY);


const result = await validator.validate(token, remoteip, {

  expectedAction: "login",

  expectedHostname: "example.com",

});


if (result.success) {

  // Process the request

} else {

  // Handle failure

  console.log("Validation failed:", result.error);

}


```

---

## Testing

You can test the dummy token generated with testing sitekey via Siteverify API with the testing secret key. Your production secret keys will reject dummy tokens.

Refer to [Testing](https://developers.cloudflare.com/turnstile/troubleshooting/testing/) for more information.

---

## Best practices

### Security

* Store your secret keys securely. Use environment variables or secure key management.
* Validate the token on every request. Never trust client-side validation alone.
* Check additional fields. Validate the action and hostname when specified.
* Monitor for abuse and log failed validations and unusual patterns.
* Use HTTPS. Always validate over secure connections.
* Only call the Siteverify API in your backend environment. If you expose the secret key in the front-end client code to call Siteverify, attackers can bypass the security check. Ensure that your client-side code sends the validation token to your backend, and that your backend is the sole caller of the Siteverify API.

### Performance

* Set reasonable timeouts. Do not wait indefinitely for Siteverify responses.
* Implement retry logic and handle temporary network issues.
* Cache validation results for the same token, if it is needed for your flow.
* Monitor your API latency. Track the Siteverify response time.

### Error handling

* Have fallback behavior for API failures.
* Use user-friendly messaging. Do not expose internal error details to users.
* Properly log errors for debugging without exposing secrets.
* Rate limit to protect against validation flooding.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/get-started/","name":"Get started"}},{"@type":"ListItem","position":4,"item":{"@id":"/turnstile/get-started/server-side-validation/","name":"Validate the token"}}]}
```

---

---
title: Create and manage widgets using Cloudflare API
description: Create and manage Turnstile widgets using the Cloudflare API.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Create and manage widgets using Cloudflare API

Use the [Cloudflare API](https://developers.cloudflare.com/api/resources/turnstile/) for programmatic widget management and automation.

## Prerequisites

Before you begin, you must have:

* A Cloudflare API token with `Account:Turnstile:Edit` permissions
* An account ID found in your Cloudflare dashboard

### Create a widget via the API

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Turnstile Sites Write`
* `Account Settings Write`

Create a Turnstile Widget

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/challenges/widgets" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "domains": [

        "example.com"

    ],

    "mode": "managed",

    "name": "My Example Turnstile Widget"

  }'


```

### Manage widgets via the API

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Turnstile Sites Write`
* `Turnstile Sites Read`
* `Account Settings Write`
* `Account Settings Read`

List Turnstile Widgets

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/challenges/widgets" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Turnstile Sites Write`
* `Turnstile Sites Read`
* `Account Settings Write`
* `Account Settings Read`

Turnstile Widget Details

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/challenges/widgets/$SITEKEY" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Turnstile Sites Write`
* `Account Settings Write`

Update a Turnstile Widget

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/challenges/widgets/$SITEKEY" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "domains": [

        "203.0.113.1",

        "cloudflare.com",

        "blog.example.com"

    ],

    "mode": "invisible",

    "name": "blog.cloudflare.com login form",

    "clearance_level": "interactive"

  }'


```

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Turnstile Sites Write`
* `Account Settings Write`

Rotate Secret for a Turnstile Widget

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/challenges/widgets/$SITEKEY/rotate_secret" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "invalidate_immediately": false

  }'


```

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Turnstile Sites Write`
* `Account Settings Write`

Delete a Turnstile Widget

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/challenges/widgets/$SITEKEY" \

  --request DELETE \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/get-started/","name":"Get started"}},{"@type":"ListItem","position":4,"item":{"@id":"/turnstile/get-started/widget-management/","name":"Widget management"}},{"@type":"ListItem","position":5,"item":{"@id":"/turnstile/get-started/widget-management/api/","name":"Create and manage widgets using Cloudflare API"}}]}
```

---

---
title: Create and manage widgets using the Cloudflare dashboard
description: Create and manage Turnstile widgets in the Cloudflare dashboard.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Create and manage widgets using the Cloudflare dashboard

The Cloudflare dashboard provides a user-friendly interface for creating and managing widgets.

## Create a widget

1. In the Cloudflare dashboard, go to the **Turnstile** page.  
[ Go to **Turnstile** ](https://dash.cloudflare.com/?to=/:account/turnstile)
2. Select **Add widget**.
3. Fill out the required information:  
   * **Widget name**: A descriptive name for your widget.  
   * **Hostname management**: Domains where the widget will be used.  
   * **Widget mode**: Choose from Managed, Non-Interactive, or Invisible.
4. (Optional) Configure **Pre-clearance support** for single-page applications.
5. Select **Create** to save your widget.
6. Copy your sitekey and secret key, and store the secret key securely.

## Manage existing widgets

You can view your widget details on the Cloudflare dashboard by selecting any existing widget to access analytics, settings, and performance metrics.

To update the widget configuration, go to any existing widget and select **Settings**. Select **Save** to apply your changes.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/get-started/","name":"Get started"}},{"@type":"ListItem","position":4,"item":{"@id":"/turnstile/get-started/widget-management/","name":"Widget management"}},{"@type":"ListItem","position":5,"item":{"@id":"/turnstile/get-started/widget-management/dashboard/","name":"Create and manage widgets using the Cloudflare dashboard"}}]}
```

---

---
title: Create and manage widgets using Terraform
description: Create and manage Turnstile widgets using the Terraform provider.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Create and manage widgets using Terraform

Manage Turnstile widgets as code using Terraform for version control and automated deployments.

## Prerequisites

Before you begin, you must have:

* [Terraform ↗](https://terraform.io/) installed
* A Cloudflare API token with `Account:Turnstile:Edit permissions`
* (Optional) A `cf-terraforming` tool for importing existing widgets

## Setup

### 1\. Configure provider

Create a `main.tf` file.

Note

Terraform code snippets below refer to the v4 SDK only.

```

terraform {

  required_providers {

    cloudflare = {

      source  = "cloudflare/cloudflare"

      version = "~> 4.0"

    }

  }

}


provider "cloudflare" {

  api_token = var.cloudflare_api_token

}


variable "cloudflare_api_token" {

  description = "Cloudflare API Token"

  type        = string

  sensitive   = true

}


variable "account_id" {

  description = "Cloudflare Account ID"

  type        = string

}


```

### 2\. Define widgets

```

resource "cloudflare_turnstile_widget" "login_form" {

  account_id = var.account_id

  name       = "Login Form Widget"

  domains    = ["example.com", "www.example.com"]

  mode       = "managed"

  region     = "world"

}


resource "cloudflare_turnstile_widget" "api_protection" {

  account_id = var.account_id

  name       = "API Protection"

  domains    = ["api.example.com"]

  mode       = "invisible"

  region     = "world"

}


# Output the sitekeys for use in your application

output "login_sitekey" {

  value = cloudflare_turnstile_widget.login_form.sitekey

}


output "api_sitekey" {

  value = cloudflare_turnstile_widget.api_protection.sitekey

}


```

### 3\. Environment variables

Create a `.env` file or set environment variables.

Terminal window

```

export TF_VAR_cloudflare_api_token="your-api-token"

export TF_VAR_account_id="your-account-id"


```

---

## Terraform commands

### Initialize and plan

Initialize Terraform

```

terraform init


```

Plan changes

```

terraform plan


```

Apply configuration

```

terraform apply


```

### Manage changes

Update widget configuration

```

terraform plan


```

Apply changes

```

terraform apply


```

Destroy widgets

```

terraform destroy


```

---

## Advanced Terraform configuration

### Multiple environments

```

locals {

  environments = {

    dev = {

      domains = ["dev.example.com"]

      mode    = "managed"

    }

    staging = {

      domains = ["staging.example.com"]

      mode    = "non_interactive"

    }

    prod = {

      domains = ["example.com", "www.example.com"]

      mode    = "invisible"

    }

  }

}


resource "cloudflare_turnstile_widget" "app_widget" {

  for_each = local.environments


  account_id = var.account_id

  name       = "App Widget - ${each.key}"

  domains    = each.value.domains

  mode       = each.value.mode

  region     = "world"

}


```

### Widget with Enterprise features

```

resource "cloudflare_turnstile_widget" "enterprise_widget" {

  account_id     = var.account_id

  name          = "Enterprise Form"

  domains       = ["enterprise.example.com"]

  mode          = "managed"

  region        = "world"

  offlabel      = true  # Remove Cloudflare branding

  bot_fight_mode = true # Enable bot fight mode

}


```

---

## Import existing widgets

Use [cf-terraforming](https://developers.cloudflare.com/terraform/advanced-topics/import-cloudflare-resources/#cf-terraforming) to import existing widgets.

Install cf-terraforming

```

go install github.com/cloudflare/cf-terraforming/cmd/cf-terraforming@latest


```

Generate Terraform configuration from existing widgets

```

cf-terraforming generate \

  --resource-type cloudflare_turnstile_widget \

  --account $ACCOUNT_ID


```

Import existing widget

```

terraform import cloudflare_turnstile_widget.existing_widget \

  $ACCOUNT_ID/$WIDGET_SITEKEY


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/get-started/","name":"Get started"}},{"@type":"ListItem","position":4,"item":{"@id":"/turnstile/get-started/widget-management/","name":"Widget management"}},{"@type":"ListItem","position":5,"item":{"@id":"/turnstile/get-started/widget-management/terraform/","name":"Create and manage widgets using Terraform"}}]}
```

---

---
title: Turnstile Analytics
description: Use Turnstile Analytics to view the number of challenges issued, the challenge solve rate, and the metrics of issued challenges.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Turnstile Analytics

Turnstile Analytics shows widget statistics across traffic dimensions like hostname, country, browser, and IP address. Use these metrics to identify where challenge activity is highest and whether specific sources are failing or bypassing challenges.

## Available statistics

* **Top Hostnames**: If the Turnstile widget is placed across multiple hostnames, this will display the highest traffic hostnames where challenges are being issued.
* **Top Browsers**: A breakdown of browsers that are most commonly encountering Turnstile challenges, helping customers spot trends in visitor traffic.
* **Top Countries**: View the top originating countries for visitors completing challenges, which can help identify regional traffic anomalies.
* **Top User Agents**: Identify which user agents are generating the most Turnstile challenge requests.
* [**Top ASNs** ↗](https://cloudflare.com/learning/network-layer/what-is-an-autonomous-system): Displays the highest volume of challenges issued from specific Autonomous System Numbers (ASNs), helping customers detect potential bot activity.
* **Top Operating Systems**: Shows which operating systems are most common among visitors passing or failing challenges.
* [**Top Source IPs** ↗](https://cloudflare.com/learning/ddos/glossary/ip-spoofing): Identify the highest-volume IP addresses issuing Turnstile challenges, which can be useful in identifying attack sources or repeated challenge failures.

## View widget metrics

To see an overview of your widget analytics:

[ Go to **Turnstile** ](https://dash.cloudflare.com/?to=/:account/turnstile) ![Turnstile Analytics overview](https://developers.cloudflare.com/_astro/top-actions.Bxq-7U4T_1hlQDM.webp) 

The metrics show changes in the solve rate, widget traffic, and top actions for your widget.

Refer to the pages below for more information about Turnstile Analytics:

* [ Challenge outcome ](https://developers.cloudflare.com/turnstile/turnstile-analytics/challenge-outcomes/)
* [ Token validation ](https://developers.cloudflare.com/turnstile/turnstile-analytics/token-validation/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/turnstile-analytics/","name":"Turnstile Analytics"}}]}
```

---

---
title: Challenge outcome
description: View challenge outcome metrics for your Turnstile widgets.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Challenge outcome

When a visitor encounters Turnstile, it assesses whether they are human or bot-like based on various signals. These outcomes help you evaluate how effectively Turnstile is protecting your application.

## Metrics

A "solved" Turnstile challenge does not automatically confirm the visitor is human. You must [call the Siteverify API](#call-siteverify) to validate the token and proceed only if the response returns `success:true`.

For example, the challenge outcome values in your analytics may look like this:

![Challenge outcome example values](https://developers.cloudflare.com/_astro/challenge-outcomes.Czqs3OEs_1uk0rH.webp "Challenge outcome example")

Challenge outcome example

* **Challenges issued**: The total number of challenges presented to visitors within a specific timeframe.
* **Challenges solved**: The number of challenges successfully completed by visitors in that period.
* **Challenges unsolved**: Challenges that were abandoned or failed in that period.
* **Likely human**: The total number of challenges solved or the total number of challenges issued.
* **Likely bot**: The total number of challenges unsolved or the total number challenges issued.

By analyzing these metrics, you can identify trends such as high failure rates in specific regions, device types, or traffic sources, which may indicate bot activity or misconfigurations.

### Call Siteverify

It is important to [call the Siteverify API](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/). Without calling Siteverify API to validate the tokens, your website or application is not protected. Skipping token validation means you cannot confirm the visitor's legitimacy.

* Tokens can only be redeemed once. Even valid tokens will return `success:false` if they are reused, preventing token theft and replay attacks.
* Tokens expire after five minutes. Validation must occur within this window to be effective.
* Tokens can be invalid. Bots might complete challenges, but Cloudflare can detect bot-like signals and mark the token as invalid.

## Solve rates

Turnstile's solve rate indicates how many visitors pass a challenge. Solve rates can be broken down into the total number of challenges solved and whether they are interactive, non-interactive, or pre-clearance solves.

If you are using [managed mode](https://developers.cloudflare.com/turnstile/concepts/widget/#managed-mode-recommended), you can monitor how many of your visitors were prompted to interact with the checkbox on the widget (interactive solves) and how many were verified without any disruptions to their experience (non-interactive solves).

For example, the solve rate values in your analytics may look like this:

![Solve rate example values](https://developers.cloudflare.com/_astro/solve-rates.YNiFNAbV_p3Ftp.webp "Solve rate example")

Solve rate example

### Metrics

* **Non-interactive solves**: Challenges solved without requiring the visitor to click a checkbox.
* **Interactive solves**: Challenges solved that required visitor interaction to be solved.
* [**Pre-clearance solves**](https://developers.cloudflare.com/cloudflare-challenges/concepts/clearance/#pre-clearance-support-in-turnstile): Challenges solved that issued the `cf_clearance` cookie along with the Turnstile token.

A low solve rate might indicate increased bot activity attempting to bypass Turnstile or anomalous traffic patterns that require further investigation.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/turnstile-analytics/","name":"Turnstile Analytics"}},{"@type":"ListItem","position":4,"item":{"@id":"/turnstile/turnstile-analytics/challenge-outcomes/","name":"Challenge outcome"}}]}
```

---

---
title: Token validation
description: View token validation metrics for your Turnstile widgets.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Token validation

After a visitor successfully completes a Turnstile challenge, a token is generated and validated via the Siteverify API. Token validation data shows how many tokens your server validated successfully versus how many failed. A high rate of invalid tokens may indicate bot activity, expired tokens, or implementation issues.

For example, the token validation values in your analytics may look like this:

![Token validation example values](https://developers.cloudflare.com/_astro/token-validation.DRmcNOiF_Z16p8LF.webp "Token validation example")

Token validation example

## Metrics

* **Siteverify requests**: The total number of requests made to the Siteverify API in the given timeframe.
* **Valid tokens**: The number of Siteverify requests with `success:true` responses.
* **Invalid tokens**: The number of Siteverify requests with `success:false` responses.

### Call Siteverify

It is important to [call the Siteverify API](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/). Without calling Siteverify API to validate the tokens, your website or application is not protected. Skipping token validation means you cannot confirm the visitor's legitimacy.

* Tokens can only be redeemed once. Even valid tokens will return `success:false` if they are reused, preventing token theft and replay attacks.
* Tokens expire after five minutes. Validation must occur within this window to be effective.
* Tokens can be invalid. Bots might complete challenges, but Cloudflare can detect bot-like signals and mark the token as invalid.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/turnstile-analytics/","name":"Turnstile Analytics"}},{"@type":"ListItem","position":4,"item":{"@id":"/turnstile/turnstile-analytics/token-validation/","name":"Token validation"}}]}
```

---

---
title: Migration
description: Migrate to Turnstile from reCAPTCHA or hCaptcha.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Migration

If you are using alternative CAPTCHA services, you can switch to Cloudflare Turnstile using the guides below to assist with the upgrade process.

[Get started with Turnstile](https://developers.cloudflare.com/turnstile/get-started/) if there is no guide available yet.

## Guides

* [reCAPTCHA](https://developers.cloudflare.com/turnstile/migration/recaptcha/)
* [hCAPTCHA](https://developers.cloudflare.com/turnstile/migration/hcaptcha/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/migration/","name":"Migration"}}]}
```

---

---
title: Migrate from hCaptcha
description: Migrate from hCaptcha to Cloudflare Turnstile.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Migrate from hCaptcha

If you are using hCaptcha today, you can switch seamlessly to Cloudflare Turnstile by following the step-by-step guide below to assist with the upgrade process.

To complete the migration, you must obtain the [sitekey and secret key](https://developers.cloudflare.com/turnstile/get-started/widget-management/).

## Client-side integration

1. Update the client-side integration by inserting the Turnstile script snippet in your HTML's `<head>` element:  
Turnstile script snippet  
```  
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>  
```
2. Locate the `hcaptcha.render()` calls and replace the sitekey with your Turnstile sitekey and the API.  
Render  
```  
  // before  
  hcaptcha.render(element, {  
      sitekey: "00000000-0000-0000-0000-000000000000"  
  })  
  // after  
  turnstile.render(element, {  
      sitekey: "1x00000000000000000000AA"  
  })  
```

Note

Turnstile supports:

* the `render()` call
* hCaptcha invisible mode with the `execute()` call

## Server-side integration

1. Update the server-side integration by replacing the Siteverify URL.  
Replace: `https://hcaptcha.com/siteverify` with the following:  
```  
https://challenges.cloudflare.com/turnstile/v0/siteverify  
```
2. Replace the `h-captcha-response` input name with the following:  
```  
cf-turnstile-response  
```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/migration/","name":"Migration"}},{"@type":"ListItem","position":4,"item":{"@id":"/turnstile/migration/hcaptcha/","name":"Migrate from hCaptcha"}}]}
```

---

---
title: Migrate from reCAPTCHA
description: Migrate from Google reCAPTCHA to Cloudflare Turnstile.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Migrate from reCAPTCHA

If you are using reCAPTCHA today, you can switch seamlessly to Cloudflare Turnstile by following the step-by-step guide below to assist with the upgrade process.

To complete the migration, you must obtain the [sitekey and secret key](https://developers.cloudflare.com/turnstile/get-started/widget-management/).

Note

Turnstile migration is currently compatible up to reCAPTCHA v2.

## Client-side integration

1. Update the client-side integration by inserting the Turnstile script snippet in your HTML's `<head>` element.  
Turnstile script snippet  
```  
<script  
  src="https://challenges.cloudflare.com/turnstile/v0/api.js?compat=recaptcha"  
  async  
  defer  
></script>  
```  
Note  
Adding `?compat=recaptcha` runs Turnstile in compatibility mode, which enables the following features:  
   * implicit rendering for reCAPTCHA  
   * `g-recaptcha-response` input name for forms  
   * register the Turnstile API as `grecaptcha`
2. Locate the `grecaptcha.render()` calls and replace the sitekey with your Turnstile sitekey.  
Note  
Turnstile supports:  
   * the `render()` call  
   * reCAPTCHA v2 invisible mode with the `execute()` call

## Server-side integration

Update the server-side integration by replacing the Siteverify URL.

Replace `https://www.google.com/recaptcha/api/siteverify` with the following:

```

https://challenges.cloudflare.com/turnstile/v0/siteverify


```

Differences to reCAPTCHA's Siteverify

reCAPTCHA supports `GET` requests using query parameters, such as `GET /siteverify?response=<response>&secret=<secret>`.

Turnstile's Siteverify endpoint does _not_ support this and only accepts `POST` requests with a FormData or JSON body.

Refer to [server-side validation](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/) for more information.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/migration/","name":"Migration"}},{"@type":"ListItem","position":4,"item":{"@id":"/turnstile/migration/recaptcha/","name":"Migrate from reCAPTCHA"}}]}
```

---

---
title: Tutorials
description: Tutorials for integrating Turnstile with WAF, login pages, and testing.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Tutorials

View tutorials to help you get started with Turnstile.

| Name                                                                                                                                              | Last Updated     | Difficulty   |
| ------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | ------------ |
| [Fraud detection with Ephemeral IDs](https://developers.cloudflare.com/turnstile/tutorials/fraud-detection-with-ephemeral-ids/)                   | 5 months ago     | Advanced     |
| [Protect your forms](https://developers.cloudflare.com/turnstile/tutorials/login-pages/)                                                          | about 1 year ago | Beginner     |
| [Conditionally enforce Turnstile](https://developers.cloudflare.com/turnstile/tutorials/conditionally-enforcing-turnstile/)                       | about 1 year ago | Intermediate |
| [Exclude Turnstile from E2E tests](https://developers.cloudflare.com/turnstile/tutorials/excluding-turnstile-from-e2e-tests/)                     | over 1 year ago  | Intermediate |
| [Integrate Turnstile, WAF, & Bot Management](https://developers.cloudflare.com/turnstile/tutorials/integrating-turnstile-waf-and-bot-management/) | over 1 year ago  | Beginner     |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/tutorials/","name":"Tutorials"}}]}
```

---

---
title: Conditionally enforce Turnstile
description: This tutorial explains how to conditionally enforce Turnstile based on the incoming request, such as a pre-shared secret in a header or a specific IP address.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Conditionally enforce Turnstile

**Last reviewed:**  about 1 year ago 

This tutorial explains how to conditionally enforce Turnstile based on the incoming request, such as a pre-shared secret in a header or a specific IP address.

## Overview

You may have setups such as automation that cannot load or run the Turnstile challenge. Using [HTMLRewriter](https://developers.cloudflare.com/workers/runtime-apis/html-rewriter/), this tutorial will demonstrate how to conditionally handle the [client-side widget](https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/) and [Siteverify API](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/) when specific criteria are met.

Note

While this tutorial removes Turnstile client-side elements when specific criteria are met, you could instead conditionally insert them.

Warning

It is critical to make sure you are validating tokens with the Siteverify API when your criteria for enforcing Turnstile are not met.

It is not sufficient to only remove the client-side widget from the page, as an attacker can forge the request to your API.

## Implementation

This tutorial will modify the existing [Turnstile demo ↗](https://github.com/cloudflare/turnstile-demo-workers/blob/main/src/) to conditionally remove the existing `script` and widget container elements.

src/index.mjs

```

export default {

  async fetch(request) {

    // ...


    if (request.headers.get("x-bypass-turnstile") === "VerySecretValue") {

      class RemoveHandler {

        element(element) {

          element.remove();

        }

      }


      return new HTMLRewriter()

        // Remove the script tag

        .on(

          'script[src="https://challenges.cloudflare.com/turnstile/v0/api.js"]',

          new RemoveHandler(),

        )

       // Remove the container used in implicit rendering

        .on(

          '.cf-turnstile',

          new RemoveHandler(),

        )

       // Remove the container used in explicit rendering

        .on(

          '#myWidget',

          new RemoveHandler(),

        )

        .transform(body);

    }


    return new Response(body, {

      headers: {

        "Content-Type": "text/html",

      },

    });

  },

};


```

## Server-side integration

We will exit early in our validation if the same logic we used to remove the client-side elements is present.

Warning

The same logic must be used in both the client-side and the server-side implementations.

src/index.mjs

```

async function handlePost(request) {

  if (request.headers.get("x-bypass-turnstile") === "VerySecretValue") {

    return new Response('Turnstile not enforced on this request')

  }

  // Proceed with validation as normal!

  const body = await request.formData();

  // Turnstile injects a token in "cf-turnstile-response".

  const token = body.get('cf-turnstile-response');

  const ip = request.headers.get('CF-Connecting-IP');

  // ...

}


```

With these changes, Turnstile will not be enforced on requests with the header `x-bypass-turnstile: VerySecretValue` present.

## Demonstration

After running `npm run dev` in the project folder, you can test the changes by running the following command:

Terminal window

```

curl -X POST http://localhost:8787/handler -H "x-bypass-turnstile: VerySecretValue"


```

```

Turnstile not enforced on this request


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/tutorials/","name":"Tutorials"}},{"@type":"ListItem","position":4,"item":{"@id":"/turnstile/tutorials/conditionally-enforcing-turnstile/","name":"Conditionally enforce Turnstile"}}]}
```

---

---
title: Exclude Turnstile from E2E tests
description: This tutorial explains how to handle Turnstile in your end-to-end (E2E) tests by using Turnstile's dedicated testing keys.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Exclude Turnstile from E2E tests

**Last reviewed:**  over 1 year ago 

This tutorial explains how to handle Turnstile in your end-to-end (E2E) tests by using Turnstile's dedicated testing keys.

## Overview

When running E2E tests, you often want to bypass or simplify the Turnstile verification process. Cloudflare provides official test credentials that always pass verification, making them perfect for testing environments:

* Test sitekey: `1x00000000000000000000AA`
* Test secret key: `1x0000000000000000000000000000000AA`

For more details, refer to the [testing documentation](https://developers.cloudflare.com/turnstile/troubleshooting/testing/).

Warning

Never use test credentials in production. Always ensure:

* Test credentials are only used in test environments.
* Production credentials are properly protected.
* Your deployment process prevents test credentials from reaching production.

## Implementation

The key to implementing test-environment detection is identifying test requests server-side. Here is a simple approach:

TypeScript

```

// Detect test environments using IP addresses or headers

function isTestEnvironment(request) {

  const testIPs = ['127.0.0.1', '::1'];

  const isTestIP = testIPs.includes(request.ip);

  const hasTestHeader = request.headers['x-test-environment'] === 'secret-token';


  return isTestIP || hasTestHeader;

}


// Use the appropriate credentials based on the environment

function getTurnstileCredentials(request) {

  if (isTestEnvironment(request)) {

    return {

      sitekey: '1x00000000000000000000AA',

      secretKey: '1x0000000000000000000000000000000AA'

    };

  }


  return {

    sitekey: process.env.TURNSTILE_SITE_KEY,

    secretKey: process.env.TURNSTILE_SECRET_KEY

  };

}


```

## Server-side integration

When rendering your page, inject the appropriate sitekey based on the environment:

TypeScript

```

app.get('/your-form', (req, res) => {

  const { sitekey } = getTurnstileCredentials(req);

  res.render('form', { sitekey });

});


```

## Client-side integration

Your template can then use the injected sitekey:

```

<div class="turnstile" data-sitekey="<%= sitekey %>"></div>


```

## Best practices

1. **Environment detection**  
   * Use multiple factors to identify test environments (IP, headers, etc.).  
   * Keep your test environment identifiers secure if you need to test from the public web.
2. **Credential management**  
   * Store production credentials securely (for example, in environment variables).  
   * Never commit credentials to version control.  
   * Use different credentials for each environment.
3. **Deployment safety**  
   * Add checks to prevent test credentials in production.  
   * Include credential validation in your CI/CD pipeline.  
   * Monitor for accidental test credential usage.

## Testing considerations

* Test credentials will always pass verification.
* They are perfect for automated testing environments.
* They help avoid rate limiting during testing.
* They make tests more predictable and faster.

## Example test setup

For Cypress or similar E2E testing frameworks:

TypeScript

```

// Set test header for all test requests

beforeEach(() => {

  cy.intercept('*', (req) => {

    req.headers['x-test-environment'] = 'secret-token';

  });

});


// Your test can now interact with the form normally

it('submits form successfully', () => {

  cy.visit('/your-form');

  cy.get('form').submit();

  // Turnstile will automatically pass verification

});


```

## Conclusion

By using Turnstile's test credentials and proper environment detection, you can create reliable E2E tests while maintaining security in production. Remember to always keep test credentials separate from production and implement proper safeguards in your deployment process.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/tutorials/","name":"Tutorials"}},{"@type":"ListItem","position":4,"item":{"@id":"/turnstile/tutorials/excluding-turnstile-from-e2e-tests/","name":"Exclude Turnstile from E2E tests"}}]}
```

---

---
title: Fraud detection with Ephemeral IDs
description: Learn how to implement fraud detection using Turnstile's Ephemeral IDs to identify and block bad actors who rotate IP addresses.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Fraud detection with Ephemeral IDs

**Last reviewed:**  5 months ago 

[Ephemeral IDs](https://developers.cloudflare.com/turnstile/additional-configuration/ephemeral-id/) let you detect fraud patterns that evade traditional IP-based detection. This tutorial will show you how to log Ephemeral IDs, detect suspicious patterns, and block bad actors.

Attackers often create hundreds of fake accounts to abuse promotions, rotate through proxy pools to avoid IP-based rate limiting, and use real browsers to evade basic bot detection.

Traditional IP-based detection fails because each request appears to come from a different address. Ephemeral IDs solve this by identifying the underlying client device, even when IP addresses change.

## Before you begin

* Ephemeral IDs require [Enterprise Bot Management](https://developers.cloudflare.com/bots/plans/bm-subscription/) with the [Enterprise Turnstile add-on](https://developers.cloudflare.com/turnstile/plans/), or [standalone Enterprise Turnstile](https://developers.cloudflare.com/turnstile/plans/). Contact your account team to enable this feature.
* You must have basic familiarity with Turnstile integration. Refer to [Get started with Turnstile](https://developers.cloudflare.com/turnstile/get-started/) for more information.

Ephemeral IDs are not guaranteed to be unique

Not every unique device will produce a unique Ephemeral ID. Privacy-focused devices and browsers (such as iPhones and Safari) limit the signals available for fingerprinting, which means multiple legitimate users may share the same Ephemeral ID.

Use Ephemeral IDs to detect high-volume abuse patterns, not to uniquely identify individual devices. Always set detection thresholds high enough to avoid false positives.

---

### Set up logging

Create a table to store events with Ephemeral IDs.

```

CREATE TABLE turnstile_events (

    id              BIGSERIAL PRIMARY KEY,

    ephemeral_id    VARCHAR(64) NOT NULL,

    event_type      VARCHAR(50) NOT NULL,  -- 'signup', 'login', 'checkout'

    ip_address      VARCHAR(45),

    user_id         VARCHAR(128),          -- NULL for signups, populated after

    created_at      TIMESTAMPTZ DEFAULT NOW()

);


CREATE TABLE blocked_ephemeral_ids (

    ephemeral_id    VARCHAR(64) PRIMARY KEY,

    reason          VARCHAR(255),

    created_at      TIMESTAMPTZ DEFAULT NOW()

);


```

### Extract and log the Ephemeral IDs

When you call Siteverify, the Ephemeral ID is returned in the `metadata` field. Log it with every protected action.

TypeScript

```

async function verifyAndLogTurnstile(

  token: string,

  ip: string,

  secretKey: string,

  eventType: string,

  db: Database,

): Promise<{ success: boolean; ephemeralId?: string; isBlocked: boolean }> {

  // Call Siteverify API

  const response = await fetch(

    "https://challenges.cloudflare.com/turnstile/v0/siteverify",

    {

      method: "POST",

      headers: { "Content-Type": "application/x-www-form-urlencoded" },

      body: new URLSearchParams({

        secret: secretKey,

        response: token,

        remoteip: ip,

      }),

    },

  );


  const result = await response.json();


  if (!result.success) {

    return { success: false, isBlocked: false };

  }


  const ephemeralId = result.metadata?.ephemeral_id;


  if (ephemeralId) {

    // Log the event

    await db.query(

      `INSERT INTO turnstile_events (ephemeral_id, event_type, ip_address)

       VALUES ($1, $2, $3)`,

      [ephemeralId, eventType, ip],

    );


    // Check if already blocked

    const blocked = await db.query(

      `SELECT 1 FROM blocked_ephemeral_ids WHERE ephemeral_id = $1`,

      [ephemeralId],

    );


    if (blocked.rows.length > 0) {

      return { success: true, ephemeralId, isBlocked: true };

    }

  }


  return { success: true, ephemeralId, isBlocked: false };

}


```

### Use the Ephemeral ID in your sign up flow

TypeScript

```

export async function handleSignup(request: Request, env: Env) {

  const formData = await request.formData();

  const email = formData.get("email") as string;

  const turnstileToken = formData.get("cf-turnstile-response") as string;

  const ip = request.headers.get("CF-Connecting-IP") || "";


  // Verify Turnstile and log the Ephemeral ID

  const verification = await verifyAndLogTurnstile(

    turnstileToken,

    ip,

    env.TURNSTILE_SECRET_KEY,

    "signup",

    env.DB,

  );


  if (!verification.success) {

    return new Response("Verification failed", { status: 400 });

  }


  // Block if this device is flagged

  if (verification.isBlocked) {

    // Return a generic message - don't reveal detection

    return new Response("Please verify your email to continue", {

      status: 202,

    });

  }


  // Proceed with normal signup

  const userId = await createUser(email, formData.get("password"));


  // Update the log with the new user ID

  if (verification.ephemeralId) {

    await env.DB.query(

      `UPDATE turnstile_events

       SET user_id = $1

       WHERE ephemeral_id = $2 AND event_type = 'signup' AND user_id IS NULL

       ORDER BY created_at DESC LIMIT 1`,

      [userId, verification.ephemeralId],

    );

  }


  return new Response("Account created", { status: 201 });

}


```

### Detect fraud patterns

Run the following query periodically (for example, every five minutes) to find suspicious Ephemeral IDs:

```

-- Find devices creating multiple accounts in the last hour

SELECT

    ephemeral_id,

    COUNT(*) as signup_count,

    COUNT(DISTINCT ip_address) as unique_ips

FROM turnstile_events

WHERE

    event_type = 'signup'

    AND created_at > NOW() - INTERVAL '1 hour'

GROUP BY ephemeral_id

HAVING COUNT(*) > 3;  -- More than 3 signups = suspicious


```

When you find suspicious IDs, block them:

```

INSERT INTO blocked_ephemeral_ids (ephemeral_id, reason)

SELECT

    ephemeral_id,

    'Multiple signups: ' || COUNT(*) || ' in 1 hour'

FROM turnstile_events

WHERE

    event_type = 'signup'

    AND created_at > NOW() - INTERVAL '1 hour'

GROUP BY ephemeral_id

HAVING COUNT(*) > 3

ON CONFLICT (ephemeral_id) DO NOTHING;


```

### Investigate and take action

When you ban accounts for abuse, find other accounts from the same device:

```

-- Find all accounts created from the same device as a banned user

SELECT DISTINCT te2.user_id, te2.created_at

FROM turnstile_events te1

JOIN turnstile_events te2 ON te1.ephemeral_id = te2.ephemeral_id

WHERE te1.user_id = 'BANNED_USER_ID'

  AND te2.user_id IS NOT NULL

  AND te2.user_id != 'BANNED_USER_ID';


```

Bulk-flag accounts for review:

```

-- Flag all accounts from a suspicious device

UPDATE users

SET status = 'under_review'

WHERE id IN (

    SELECT DISTINCT user_id

    FROM turnstile_events

    WHERE ephemeral_id = 'x:SUSPICIOUS_ID_HERE'

      AND user_id IS NOT NULL

);


```

---

## Recommendations

Privacy

Ephemeral IDs are privacy-preserving. They are scoped to your account, short-lived, and cannot identify individuals across sites.

* **Log immediately**: Capture the Ephemeral ID right when you call Siteverify.
* **Silent rejection**: When blocking fraud, return generic errors. Never reveal that you detected the device.
* **Tune thresholds**: Start conservative (for example, three sign ups per hour) with the query and adjust based on your traffic.
* **Combine signals**: Use Ephemeral IDs alongside IP reputation and behavior analytics.

---

## Related resources

* [Ephemeral IDs](https://developers.cloudflare.com/turnstile/additional-configuration/ephemeral-id/)
* [Server-side validation](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/)
* [Integrate Turnstile, WAF, and Bot Management](https://developers.cloudflare.com/turnstile/tutorials/integrating-turnstile-waf-and-bot-management/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/tutorials/","name":"Tutorials"}},{"@type":"ListItem","position":4,"item":{"@id":"/turnstile/tutorials/fraud-detection-with-ephemeral-ids/","name":"Fraud detection with Ephemeral IDs"}}]}
```

---

---
title: Integrate Turnstile, WAF, &amp; Bot Management
description: This tutorial will guide you on how to integrate Cloudflare Turnstile, Web Application Firewall (WAF), and Bot Management. This combination creates a robust defense against various threats, including automated attacks and malicious login attempts.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Integrate Turnstile, WAF, & Bot Management

**Last reviewed:**  over 1 year ago 

This tutorial will guide you on how to integrate Cloudflare Turnstile, [Web Application Firewall (WAF)](https://developers.cloudflare.com/waf/), and [Bot Management](https://developers.cloudflare.com/bots/get-started/bot-management/) into an existing authentication system. This combination creates a robust defense against various threats, including automated attacks and malicious login attempts.

## Overview

To use WAF and Bot Management, your site must have its DNS pointing through Cloudflare. However, Turnstile can be used independently on any site including those not on Cloudflare's network. This tutorial will cover how to implement all three products, but you can focus on Turnstile if your site is not on Cloudflare's network.

WAF, Bot Management, and Turnstile work well together by operating on different layers of the application:

* WAF filters malicious traffic based on network signals.
* Bot Management analyzes requests to identify and mitigate automated threats.
* Turnstile examines client-side and browser signals to distinguish between human users and bots.

By combining server-side (WAF and Bot Management) and client-side (Turnstile) security measures, you can combine multiple layers of defense to create a protection system that is difficult for attackers to circumvent.

## Before you begin

* You must have a Cloudflare account with access to WAF and Bot Management (if using).
* An existing JavaScript/TypeScript-based route handling authentication.

This tutorial uses a simple login form written in plain HTML to demonstrate how to integrate Turnstile into your application. In the backend, a stubbed out authentication route, written in TypeScript, will handle the login request. You may replace this with the language of your choice. As long as your language or framework is able to make an external HTTP request to [Turnstile's API](https://developers.cloudflare.com/api/resources/turnstile/subresources/widgets/methods/create/), you can integrate Turnstile into your application.

## Configure WAF and Bot Management

If your site is on Cloudflare's network and subscribed to an Enterprise plan, you must configure WAF and Bot Management.

### Issue challenges for potential bot traffic

1. In the Cloudflare dashboard, go to the **WAF** page.  
[ Go to **WAF** ](https://dash.cloudflare.com/?to=/:account/application-security/waf)
2. Create a new custom WAF rule by selecting **Edit expression**:  
   * Field: "Bot Score"  
   * Operator: "less than or equal to"  
   * Value: "30"  
   * Action: "Managed Challenge"

This configuration challenges requests with a low bot score, leveraging network signals to identify potential threats before they reach your application. You may customize the score threshold based on your specific use case.

## Set up Cloudflare Turnstile

Turnstile can be used on any site, regardless of whether it is on Cloudflare's network:

1. In the Cloudflare dashboard, go to the **Turnstile** page.  
[ Go to **Turnstile** ](https://dash.cloudflare.com/?to=/:account/turnstile)
2. Select **Add widget** and fill out the necessary information.
3. Add your domain to the Turnstile configuration.
4. Select **Create**.

Turnstile adds an extra layer of security by analyzing browser and client-side signals, complementing the server-side checks performed by WAF and Bot Management.

### Enable the option to use the existing clearance cookie

If your site is on Cloudflare, you can enable the option to use the existing [clearance cookie](https://developers.cloudflare.com/cloudflare-challenges/concepts/clearance/#pre-clearance-support-in-turnstile) in Turnstile's settings. This integration allows Turnstile to use the clearance cookie as part of its determination of whether a user should receive a challenge. This integration is optional, but recommended if you already are using WAF and Bot Management.

## Integrate Turnstile into your application

There are two components to implementing Turnstile into your application: the Turnstile widget and the server-side validation logic.

### Add the Turnstile widget to your login form

Add the Turnstile widget to your existing login form:

```

<form id="login-form">

  <input type="text" id="username" placeholder="Username" required />

  <input type="password" id="password" placeholder="Password" autocomplete="off" required />

  <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>

  <button type="submit">Log in</button>

</form>


<script

  src="https://challenges.cloudflare.com/turnstile/v0/api.js"

  async

  defer

></script>


```

Replace `<YOUR-SITE-KEY>` with your actual Turnstile site key.

## Handle the login request

In your existing authentication route, add Turnstile validation:

TypeScript

```

async function validateTurnstileToken(

  ip: string,

  token: string,

  secret: string,

): Promise<boolean> {

  const response = await fetch(

    "https://challenges.cloudflare.com/turnstile/v0/siteverify",

    {

      method: "POST",

      headers: { "Content-Type": "application/json" },

      body: JSON.stringify({ ip, secret, response: token }),

    },

  );


  const outcome = await response.json();

  return outcome.success;

}


// Assume that this is a TypeScript route handler.

// You may replace this with a different implementation,

// based on your language or framework

export async function onRequestPost(context) {

  const { request, env } = context;

  const { username, password, token } = await request.json();


  // Validate Turnstile token

  const secretKey = env.TURNSTILE_SECRET_KEY;

  const ip = request.headers.get("CF-Connecting-IP");

  const turnstileValid = await validateTurnstileToken(ip, token, secretKey);

  if (!turnstileValid) {

    // Return back to the login page with an error message

    return Response.redirect("/login", 302, {

      headers: {

        Location: "/login?error=invalid-turnstile-token",

      },

    });

  }


  // Perform your existing authentication logic here

  const isValidLogin = await checkCredentials(username, password);


  if (isValidLogin) {

    return new Response(JSON.stringify({ message: "Login successful" }), {

      status: 200,

      headers: { "Content-Type": "application/json" },

    });

  } else {

    return new Response(JSON.stringify({ error: "Invalid credentials" }), {

      status: 401,

      headers: { "Content-Type": "application/json" },

    });

  }

}


async function checkCredentials(

  username: string,

  password: string,

): Promise<boolean> {

  // Your existing credential checking logic

}


```

This setup ensures that the Turnstile token is validated on the server-side before proceeding with the login process, adding an extra layer of security based on client-side signals.

## Testing

After deployment, you will want to test your integration. Because your bot score will be low, you will probably not receive a challenge. However, you can add additional rules as needed to force a redirect to the challenge page. Some options to do this are:

1. Add a WAF rule that always forwards your IP address to the challenge page.
2. Add a WAF rule that checks for the presence of a query parameter, such as `?challenge=true`.

## Best practices

1. Always validate the Turnstile token on the server-side before checking credentials.
2. Use environment variables to store sensitive information like your Turnstile secret key.
3. Implement proper error handling and logging to monitor for potential security issues.

By combining Turnstile with WAF and Bot Management, you can create a system that secures your application at the network layer, while also providing an extra layer of protection using client-side signals. This approach makes it significantly more difficult for malicious actors to automate attacks against your login system.

## Resources

If you are interested in customizing Turnstile, refer to the resources below for more information:

* [Client-side rendering](https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/). Learn how to customize how and when Turnstile renders in your user interface, to better fit your application's needs and user experience.
* [Server-side validation](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/). Learn how Turnstile's API works, including request parameters, as well as how to handle different types of responses, including error codes.
* [Turnstile Analytics](https://developers.cloudflare.com/turnstile/turnstile-analytics/). Learn how to view Turnstile's analytics in the Cloudflare dashboard. This includes metrics on the number of challenges issued, as well as the [challenge solve rate (CSR)](https://developers.cloudflare.com/cloudflare-challenges/reference/challenge-solve-rate/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/turnstile/","name":"Turnstile"}},{"@type":"ListItem","position":3,"item":{"@id":"/turnstile/tutorials/","name":"Tutorials"}},{"@type":"ListItem","position":4,"item":{"@id":"/turnstile/tutorials/integrating-turnstile-waf-and-bot-management/","name":"Integrate Turnstile, WAF, & Bot Management"}}]}
```

---

---
title: Protect your forms
description: This tutorial will guide you through integrating Cloudflare Turnstile to protect your web forms, such as login, signup, or contact forms.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/turnstile/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Protect your forms

**Last reviewed:**  about 1 year ago 

This tutorial will guide you through integrating Cloudflare Turnstile to protect your web forms, such as login, signup, or contact forms. Learn how to implement the Turnstile widget on the client side and verify the Turnstile token via the Siteverify API on the server side.

## Before you begin

* You must have a Cloudflare account.
* You must have a web application with a form you want to protect.
* You must have basic knowledge of HTML and your server-side language of choice, such as Node.js or Python.

## Get Your Turnstile sitekey and secret key

1. In the Cloudflare dashboard, go to the **Turnstile** page.[ Go to **Turnstile** ](https://dash.cloudflare.com/?to=/:account/turnstile)
2. [Create a new Turnstile widget](https://developers.cloudflare.com/turnstile/get-started/).
3. Copy the sitekey and the secret key to use in the next step.

## Add the Turnstile widget to your HTML form

1. Add the Turnstile widget to your form.
2. Replace `<YOUR-SITE-KEY>` with the sitekey from Cloudflare.
3. Add a `data-callback` attribute to the Turnstile widget div. This JavaScript function will be called when the challenge is successful.
4. Ensure your submit button is initially disabled.

Example

```

<!DOCTYPE html>

<html lang="en">

  <head>

    <meta charset="UTF-8" />

    <title>Contact Form</title>

    <script

      src="https://challenges.cloudflare.com/turnstile/v0/api.js"

      async

      defer

    ></script>

    <script>

      function enableSubmit() {

        document.getElementById("submit-button").disabled = false;

      }

    </script>

  </head>

  <body>

    <form id="contact-form" action="/submit" method="POST">

      <input type="text" name="name" placeholder="Name" required />

      <input type="email" name="email" placeholder="Email" required />

      <textarea name="message" placeholder="Message" required></textarea>


      <!-- Turnstile widget -->

      <div

        class="cf-turnstile"

        data-sitekey="<YOUR-SITE-KEY>"

        data-callback="enableSubmit"

      ></div>


      <button type="submit" id="submit-button" disabled>Submit</button>

    </form>

  </body>

</html>


```

## Verify the Turnstile token on the server side

You will need to verify the Turnstile token sent from the client side. Below is an example in Node.js.

Node.js example

```

const express = require("express