# Fix the Cloudflare Auto Minify hydration error

> A Cloudflare Auto Minify hydration error happens when a CDN rewrites server HTML on its way to the browser. Turn off HTML minification and email obfuscation.

Source: https://hydration.jscrate.dev/docs/causes/cdn
Last updated: 2026-09-18

A Cloudflare Auto Minify hydration error happens when a CDN or proxy rewrites
the server's HTML on its way to the browser. Minification drops the whitespace
between elements, email obfuscation replaces addresses, and injected scripts
change the page, so React hydrates HTML its server never produced. Turn HTML
rewriting off for server-rendered pages.

## Symptoms

The app works locally and on a preview deployment, and fails only behind the
CDN:

```text
Hydration failed because the server rendered text didn't match the client.
Text content does not match server-rendered HTML.
Minified React error #418; visit https://react.dev/errors/418
```

hydration-proof reports whitespace-only differences as
[HP1015](https://hydration.jscrate.dev/docs/issues/hp1015) and HTML changed between the origin and the
browser as [HP4003](https://hydration.jscrate.dev/docs/issues/hp4003), with the cause **HTML rewritten by a
CDN or proxy**. When only whitespace differs and the response carries a CDN
header (`cf-ray`, `x-amz-cf-id`, `x-served-by`, `x-cache`, `via`), it names the
cause with 88% confidence.

## Why a Cloudflare Auto Minify hydration error happens

React renders text and spaces as separate pieces: `Hello{" "}<strong>world</strong>`
needs the space between the text and the element. An HTML minifier removes
"unneeded" whitespace between tags, the browser parses the shorter HTML, and
React's first render no longer matches it. Minifiers that strip HTML comments
do more damage: React's server HTML uses comments to separate adjacent text
nodes and to mark Suspense boundaries.

CDN features that rewrite HTML:

| Feature                          | What it changes                                                           | Turn it off                                                                                                                                                                                                                                                            |
| -------------------------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Auto Minify (HTML)               | Removes whitespace and comments                                           | Cloudflare deprecated Auto Minify on August 5, 2024. A zone that still has it on can turn it off through the API, as Cloudflare's [Turn off Auto Minify](https://developers.cloudflare.com/speed/optimization/content/troubleshooting/disable-auto-minify/) page shows |
| Email Address Obfuscation        | Replaces visible email addresses with a link and adds a decode script     | Security, Settings, Client-side abuse, Email Address Obfuscation: Off. A configuration rule can turn it off for some paths only                                                                                                                                        |
| Rocket Loader                    | Defers all JavaScript until after rendering, rewriting the page's scripts | Speed, Settings, Content Optimization, Rocket Loader: Off. `data-cfasync="false"` before `src` excludes one script                                                                                                                                                     |
| Other proxies and edge functions | Minify, inject banners or analytics, rewrite links                        | Check the proxy's HTML settings                                                                                                                                                                                                                                        |

Cloudflare documents the email feature in
[Email Address Obfuscation](https://developers.cloudflare.com/waf/tools/scrape-shield/email-address-obfuscation/)
and the script feature in
[Rocket Loader](https://developers.cloudflare.com/speed/optimization/content/rocket-loader/).

## How to fix it

1. Turn off HTML minification at the CDN for server-rendered pages. Your
   framework's build already minifies JavaScript and CSS; the HTML does not
   need a second pass.
2. Turn off Email Address Obfuscation, or exclude your app's paths with a
   configuration rule. If you want to hide addresses from scrapers, do it in
   your own components.
3. Turn off Rocket Loader for the app. React and your framework load their own
   scripts in a specific order.
4. Test through the CDN again. The finding disappears once the HTML arrives
   unchanged.

Purge the CDN cache after changing the settings, or cached pages keep the
rewritten HTML.

## Fix an iOS format-detection hydration mismatch

Safari on iOS does its own rewriting: by default it detects strings that look
like phone numbers and turns them into links that call the number. When that
happens to server HTML before React hydrates, the DOM holds an `<a>` React did
not render. Turn the detection off with a meta tag:

```html title="index.html"
<meta name="format-detection" content="telephone=no" />
```

In the Next.js App Router, set it through the metadata API:

```tsx title="app/layout.tsx"
import type { Metadata } from "next";

export const metadata: Metadata = {
  formatDetection: {
    telephone: false,
    email: false,
    address: false,
  },
};
```

Next.js renders that as
`<meta name="format-detection" content="telephone=no, address=no, email=no" />`.
Render phone numbers you want linked as real `tel:` links yourself. The desktop
browsers hydration-proof drives may not do this detection, so check this one on
a real iPhone.

## Catch it with ESLint

A CDN setting is not code, so no lint rule can catch it.

## Catch it in CI

Run hydration-proof against the origin and against the CDN. A finding that
only appears through the CDN is the CDN:

```bash
npx hydration-proof test --url https://origin.example.com --route / --route /contact
npx hydration-proof test --url https://www.example.com --route / --route /contact
```

The CDN run reports HP1015 or HP4003, with the CDN header that pointed at the
cause in the reason. See [CI](https://hydration.jscrate.dev/docs/ci) for running this against a staging
deployment.

## Related

- [HP1015: whitespace differs between server and client](https://hydration.jscrate.dev/docs/issues/hp1015)
- [HP4003: HTML was rewritten between the server and the browser](https://hydration.jscrate.dev/docs/issues/hp4003)
- [Errors only in production](https://hydration.jscrate.dev/docs/guides/hydration-error-only-in-production)
- [Scripts that change the page before hydration](https://hydration.jscrate.dev/docs/causes/third-party-script)
- [All causes of hydration errors](https://hydration.jscrate.dev/docs/causes)
