Speed

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:

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:

Improve your network score

You have a few options to help improve network scores.

Glossary

import { Glossary } from "~/components"

Review the definitions for terms used across Cloudflare's Speed documentation.

Speed

import { CardGrid, Description, Feature, LinkTitleCard, Plan, RelatedProduct } from "~/components"

Improve the performance of your website or web application.

Speed allows you to assess the performance of your website and get recommendations of Cloudflare products to enhance the website performance.


Features

Use Observatory to conduct tests with both synthetic and real user data to identify potential website performance enhancements.

See how your origin server responds to Cloudflare. Identify slow endpoints, monitor response times, and diagnose errors.

Get recommendations of Cloudflare products and settings to improve your website’s performance.

Understand your Internet quality to identify scenarios that your Internet connection is good or bad for.


Customize the cache properties of your HTTP requests. Understand the performance of your webpages as experienced by your site visitors. Transform images on Cloudflare's edge platform: resize, adjust quality, and convert images to WebP or AVIF format on demand. 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

Learn about the quota limits for the number of tests you can run per month.

Engage with other users and explore more resources on Cloudflare support forum.

Origin Analytics

Origin Analytics shows how your origin server responds to Cloudflare, using data collected at the edge without an agent on your origin.

Use Origin Analytics to identify slow endpoints, monitor origin response times, and diagnose errors. When something goes wrong, Origin Analytics shows whether the source is your origin, the network path, or Cloudflare. For common error codes, refer to Cloudflare 5xx errors.

View Origin Analytics

To open the Origin Analytics tab:

  1. Log in to the Cloudflare dashboard and select your account and domain.
  2. Go to Speed > Origin Analytics.

Metrics

The dashboard displays the following metrics, derived from your zone's edge logs.

Origin response time

Use this metric to spot slowdowns and catch requests approaching your timeout threshold before they result in 524 errors.

Origin response time shows how long your origin takes to respond to Cloudflare, measured at the 50th, 95th, and 99th percentiles. A reference line indicates your zone's configured origin timeout.

The clock starts when Cloudflare decides the request must go to origin (a cache miss) and stops when Cloudflare receives the response headers — not the full body — back from your origin. It includes DNS resolution, TCP and TLS handshakes, request transmission, origin processing, and response receipt. If Argo Smart Routing or Tiered Cache is enabled, the metric also includes time spent routing through those services.

Because this measures the full upstream round trip, Origin Analytics shows higher response times than your origin's own monitoring tools (for example, Grafana or Datadog), which measure only server-side processing time.

Origin status codes

Use this metric to understand what your origin actually returned when users report errors. The error code the end user sees can differ from what your origin returned, because Cloudflare wraps certain origin failures in its own error codes (such as 520, 522, or 524).

Origin Analytics shows both values: the response code from your origin (originResponseStatus) and the code Cloudflare served to the end user (edgeResponseStatus). Status codes are grouped by class (2xx, 3xx, 4xx, 5xx) and shown over time.

The following table shows common scenarios where these values differ:

What happened originResponseStatus edgeResponseStatus
Origin returned 200 with malformed headers 200 520
Origin returned a server error 503 503 or 520
Origin closed the connection mid-response 0 520
Origin did not respond in time 0 524
TCP connection to origin failed 0 522
Request served from cache 0 200
Worker handled the request 0 Varies

A status code of 0 means Cloudflare did not receive an HTTP response from the origin. This can indicate a connection failure, a timeout, or that the request was served from cache or handled by a Worker before reaching the origin.

Top endpoints

Use this table to narrow down which specific path is causing slowdowns or errors. Request paths are ranked by P95 response time, error rate, request volume, or TCP failure rate.

Common diagnostic flows

The following table describes how to use Origin Analytics to investigate common origin errors.

Issue What to check
524 timeout errors Origin response time chart. If P95 is approaching the timeout threshold, identify slow paths in the Top endpoints table.
522 connection errors Verify that your firewall allows Cloudflare IP ranges and that your origin is listening on the expected port.
520 unknown errors Origin status code chart. If the origin returned a 200 but Cloudflare served a 520, the origin response was malformed (for example, oversized headers or an early connection close).

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:

These recommendations will vary based on your site's observed performance.

Selecting a suggestion expands it to show more detail:

Core Web Vitals

The dashboard integrates Core Web Vitals, showing values at the 75th percentile (p75). These metrics reflect real user experiences:

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.

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:

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:

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:

FAQ

import { Render, DashButton } from "~/components";

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 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.

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:

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:

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.

  2. Select Manage Site for the hostname for which you wish to disable RUM.

  3. Select Delete.

Observatory (beta)

import { LinkButton } from "~/components";

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.

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 your own websites. 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, devices, browsers, browser extensions and other software competing for resources. Real user data also includes a user interaction metric that synthetic tests do not offer: Interaction to Next Paint (INP).

Free customers have RUM enabled automatically, with traffic from EEA/UK/CH excluded, and can switch it off if they prefer. Customers on other plans may enable RUM as needed.

Run test

RUM beacon for Web Analytics

The RUM beacon is a JavaScript snippet that runs when a Cloudflare customer enables RUM through Web Analytics or 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 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:

Data collection

Once downloaded to the browser, the RUM beacon script runs as JavaScript in the browser. It collects performance data from browser APIs 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/ The referring page URL. If it is a multi-page application (MPA), then it is generated from 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
memory { totalJSHeapSize: 39973671, usedJSHeapSize: 39127515, jsHeapSizeLimit: 4294705152 } Measures memory heap size. performance.memory (deprecated)
timings Object of PerformanceTiming Timing data. performance.timing (deprecated, fallback when timingV2 is unavailable)
timingV2 Object of PerformanceNavigationTiming Navigation timing data. performance.getEntriesByType("navigation")
firstPaint Array of PerformancePaintTiming Paint timing data. performance.getEntriesByType("paint")
firstContentfulPaint 209 First Contentful Paint metric. web-vitals module [^1]
FCP 209 First Contentful Paint metric. web-vitals module [^1]
LCP 209 Largest Contentful Paint metric. web-vitals module [^1]
CLS 0.001 Cumulative Layout Shift metric. web-vitals module [^1]
TTFB 0.03 Time to First Byte metric. web-vitals module [^1]
INP 1.23 Interaction to Next Paint metric. web-vitals module [^1]
landingPath https://cfrumtest.com/ The landing page URL. performance.getEntriesByType("navigation")

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 and Unimog. 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, localStorage, sessionStorage, IP address, or IndexedDB. The data we collect is performance data from the browser performance APIs. 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.

<div class="medium-img">

![Enable RUM in the dashboard.](~/assets/images/speed/enable-rum.png)

</div>

[^1]: The web-vitals module is an open-source module written by Google. It does not access any type of storage on the browser.

Run test

import { Render, DashButton } from "~/components";

Run Synthetic test

  1. In the Cloudflare dashboard, go to the Synthetic Monitoring page.

  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 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 for more information.

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 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 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

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) Measures the time between the request for a resource and when the first byte of a response begins to arrive.
First Contentful Paint (FCP) 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) CP reports the render time of the largest image or text block visible within the viewport.
Cumulative Layout Shift (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) 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) 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 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) 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 for more information about the metrics you can find in the Real User Monitoring dashboard. You can find details about 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) 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.

Settings

import { DirectoryListing } from "~/components"

The Optimization section will show you a list of Cloudflare products that are recommended for enhancing your website's performance.

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 on your website. This analytics tool leverages Real User Measurement (RUM) data, providing insights based on actual user interactions to enhance site performance effectively.

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.

Content compression

import { Stream, Render } from "~/components";

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, Cloudflare supports Gzip, Brotli, and Zstandard compression when delivering content to website visitors.

:::note Customers can enable Zstandard compression through 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:

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.

:::caution[Minimum response size for compression]

Cloudflare will only apply compression to responses with a minimum size when sending them to website visitors:

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:

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.

:::caution 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. :::


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.

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.

Content optimizations

import { DirectoryListing } from "~/components"

Prefetch URLs

import { Example, TabItem, Tabs, DashButton } from "~/components";

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 — 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 and include a list of URLs to prefetch.

Enable Prefetch URLs

To enable Prefetch URLs in the dashboard:

  1. In the Cloudflare dashboard, go to the Speed > Settings page.

  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 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, 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: ; 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[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:

Limitations

Shared dictionaries

import { TabItem, Tabs, CURL, DashButton } from "~/components";

Shared dictionaries (RFC 9842) 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.


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:


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, 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 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

To enable shared dictionaries in the dashboard:

  1. In the Cloudflare dashboard, go to the Speed Settings page.

  2. Go to Content Optimization.

  3. Toggle Shared Dictionaries to On.

Use the following PATCH request to enable shared dictionaries:

<CURL url="https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/shared_dictionary_mode" method="PATCH" headers={{ 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.

:::note Because shared_dictionary_mode is a zone setting, it is not compatible with Cloudflare 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 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:


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.

# 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 to confirm your browser supports shared dictionaries and to inspect a working delta-compressed response.


Limitations

Speed Brain

import { TabItem, Tabs, APIRequest, DashButton } from "~/components";

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:

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 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 (LCP), Time to First Byte (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.

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 for more details. For more general information about debugging Speculation-Rules, refer to the Chrome Speculation Debugging guide.

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 documentation.

Enable and disable Speed Brain

Speed Brain is available in Cloudflare's Speed tab of the dashboard and also in the API.

To enable or disable Speed Brain in the dashboard:

  1. In the Cloudflare dashboard, go to the Speed > Settings page.

  2. Go to Content Optimization.

  3. Toggle Speed Brain to On or Off.

Use the following PATCH request to enable Speed Brain:

<APIRequest path="/zones/{zone_id}/settings/speed_brain" method="PATCH" 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.

Caveats

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 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.

Cloudflare Fonts

import { GlossaryTooltip, Render, DashButton } from "~/components";

Cloudflare Fonts is a feature designed for websites that use Google Fonts. 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.

  2. Go to Content Optimization.

  3. For Cloudflare Fonts, switch the toggle to On.

Limitations

While Cloudflare Fonts offers powerful font optimization capabilities, it is important to be aware of its limitations:

Troubleshooting

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 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:

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 pages or contact Cloudflare Support for assistance.

Enable

import { Render, TabItem, Tabs, DashButton } from "~/components";

To enable or disable Rocket Loader, use the following instructions.

To enable or disable Rocket Loader in the dashboard:

  1. In the Cloudflare dashboard, go to the Speed > Settings page.

  2. Go to Content Optimization.

  3. For Rocket Loader, switch the toggle to On.

To enable or disable Rocket Loader with the API, send a PATCH request with rocket_loader as the setting name in the URI path, and the value parameter set to "on" or "off".

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 to exclude that page by URL.

:::

Limitations

Rocket Loader

import { DirectoryListing, Render } from "~/components";

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 for your users and improves the following performance metrics:

How to

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. These failures do not correlate to issues for your site visitors.

If you observe JavaScript or jQuery issues for your website, disable Rocket Loader and retest your website.


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 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 and in HTML charset attribute.

Alternatively, you can use a Configuration Rule 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:

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.

Turn off Auto Minify via API

If your site is still using deprecated features for Auto Minify, turn off Auto Minify via API.

Before you begin

You will need an API token with the following permissions:

(Optional) Check zone status

To check your zone's Auto Minify status, send a GET request to the /zones/{zone_id}/settings/minify endpoint.

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.

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": []
}

Troubleshooting

import { DirectoryListing } from "~/components"

Image optimization

import { DirectoryListing } from "~/components"

Cloudflare Mirage (deprecated)

:::caution[Deprecation notice] Mirage was deprecated on September 15, 2025 and is no longer available.

As an alternative, Cloudflare recommends using lazy loading and 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:

Why was it deprecated?

Modern web standards and browser capabilities have evolved to provide native support for many of Mirage's features:

Migration path

Instead of Mirage, use:

Troubleshooting

import { DirectoryListing } from "~/components"

Image optimization on optimized images

Cloudflare's image optimization features 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.

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:

  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.

0-RTT Connection Resumption

import { TabItem, Tabs, DashButton } from "~/components";

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.

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.

To enable 0-RTT Connection Resumption in the dashboard:

  1. In the Cloudflare dashboard, go to the Speed > Settings page.

  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 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. :::

Security considerations

0-RTT reduces latency by allowing requests before the connection handshake completes. By design, these requests can be replayed and, for QUIC, processed before the client source IP address is validated. Before enabling 0-RTT, evaluate whether these risks are compatible with your security requirements.

Enhanced HTTP/2 Prioritization

import { TabItem, Tabs } from "~/components";

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.

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.

Enable Enhanced HTTP/2 Prioritization

To enable Enhanced HTTP/2 Prioritization in the Cloudflare dashboard:

  1. Log into the Cloudflare dashboard.
  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 with h2_prioritization as the setting name in the URI path, and the value parameter set to "on".

HTTP/2 to Origin

import { Details, Render, APIRequest, DashButton, } from "~/components";

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.

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.

  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:

Connections are kept alive and reused until they become idle or hit their concurrency limit.

Connection lifecycle

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

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.

  1. Log in to the Cloudflare dashboard 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.

<APIRequest path="/zones/{zone_id}/settings/origin_h2_max_streams" method="PATCH" json={{ value: 100, }} />

Refer to the API documentation for more information.

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 125s (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 125 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 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.

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).

HTTP/2

import { TabItem, Tabs } from "~/components";

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.

:::

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).

Disable HTTP/2

Domains on Free plans cannot disable Cloudflare's HTTP/2 setting.

To disable HTTP/2 in the dashboard:

  1. Log into the Cloudflare dashboard.
  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 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:

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.

You can also review your origin server's compression settings to make sure the compression is working as expected.

HTTP/3 (with QUIC)

import { TabItem, Tabs } from "~/components";

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.

:::

:::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).

To enable HTTP/3 in the dashboard:

  1. Log into the Cloudflare dashboard.
  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 request with http3 as the setting name in the URI path, and the value parameter set to "on".

Protocol optimization

import { DirectoryListing } from "~/components"

Enhanced HTTP/2 Prioritization negatively affects iOS/Safari devices

Occasionally, Enhanced HTTP/2 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.

:::note

Sometimes, HTTP/2 will cause Enhanced HTTP/2 Prioritization to be re-enabled automatically.

If you notice this happening, also disable HTTP/2.

:::

Troubleshooting

import { DirectoryListing } from "~/components"

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

H2 Multiplexing - Origin incompatibility/issues

Generic browser errors

Common browser errors include:

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.

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) — Cloudflare's QUIC implementation is not the cause.

Symptoms can include:

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.

Troubleshooting

import { ResourcesBySelector } from "~/components"

The following topics are useful for troubleshooting Speed issues.

<ResourcesBySelector directory="speed" types={["faq", "troubleshooting"]} filterables={["pcx_content_type"]} showDescriptions={false} />

Troubleshooting a slow website

import { Details, DashButton, Tabs, TabItem, GlossaryTooltip } from "~/components";

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 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 dig +short www.example.com ``` ```powershell Resolve-DnsName -Name www.example.com | Select-Object -ExpandProperty IPAddress ```

The returned IP addresses should be Cloudflare IPs. If they point directly to your origin server, your DNS records are not proxied.

To fix this:

  1. Go to the Cloudflare dashboard.
  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 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.

  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.

Based on Observatory results, enable relevant Speed optimizations:


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:


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:

For a full guide on available metrics, diagnostic flows, and how to interpret origin status codes, refer to Origin Analytics.

Check for slow Workers

If your zone has Cloudflare 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:


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 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:


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 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 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.

Use Cache Analytics

  1. Go to the Cloudflare dashboard.

  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 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
BYPASS status A Cache Rule is bypassing cache Review your 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
MISS with query strings Different query strings create different cache entries Use a custom cache key to ignore or normalize query strings

Cache additional static content

By default, Cloudflare only caches certain file extensions. To cache additional static content:

  1. Go to Caching > Cache Rules.
  2. Create a rule to cache specific content.
  3. Set appropriate Edge TTLs.

:::caution 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 Rules simulator 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:


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 to test:

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.

mtr -rw www.example.com

Download WinMTR and run it with your domain as the target.

Look for:

For more details, refer to How to read 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 to test the network path between your origin and Cloudflare.

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 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 also check the cf-ray response header. The three-letter code at the end of the value identifies the data center that processed the request. You can find the full list of Cloudflare data centers and their codes on the Cloudflare status page.

Why routing matters

When a request reaches Cloudflare:

  1. The request is routed to a Cloudflare data center based on anycast routing. This is not always the data center closest geographically.
  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

Requests may be sent to data centers that are not the closest geographically. Cloudflare continuously adds capacity to its global network and improves its automated traffic engineering systems to manage congestion and other network events. Cloudflare aims to serve traffic from the closest location for the best performance, but reliability takes priority.

When performance and reliability conflict, Cloudflare's systems prioritize a stable connection over a local one.

Cloudflare does not pick a data center for each visitor. The visitor's Internet service provider (ISP) decides which Cloudflare data center receives the request, based on its own routing and peering policies. These policies do not always favor the geographically closest location. For example, an ISP may send traffic to a distant city where it has a direct connection with Cloudflare instead of a nearby one where it does not.

Cloudflare's traffic engineering can influence these paths across the network as a whole, but it cannot direct individual visitors to a specific data center. Data center selection cannot be configured per zone, per account, or by support request.

For more details, refer to Cloudflare traffic not being sent to the geographically closest data center.

Common causes of unexpected routing:

Symptom Explanation
Requests route to a distant data center Cloudflare traffic engineering for reliability, or ISP routing decisions
cf-ray shows a different location than a traceroute Traffic can enter Cloudflare's network at one location and be processed at another
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 Use upper-tier data centers to reduce origin requests Sites with global traffic
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 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, which bundles multiple Cloudflare performance and reliability features.

To enable Argo Smart Routing:

  1. Go to the Cloudflare dashboard.
  2. Follow the Smart Shield setup guide to enable the feature.

Argo is particularly effective when:

For detailed information about how Argo Smart Routing works, refer to the Argo Smart Routing documentation.


Contact Support if the problem persists

If you have followed the steps above and the performance issue persists, contact Cloudflare Support for assistance.

When contacting Support, provide as much evidence as possible to help diagnose the issue:

The more evidence you provide showing the slowness, the faster Support can identify and resolve the issue.