Hydration Proof

Search documentation

Find a page or section

Fix a browser extension hydration error

Not your code. Confirm it, then move on.

A browser extension hydration error happens when an extension changes the page before React hydrates. React then sees attributes or elements the server did not send. First reproduce the page in a clean browser profile. Ignore the difference only after you have confirmed its source.

Symptoms

The warning may name an unfamiliar attribute on <html>, <body>, or a form field:

Warning: Extra attributes from the server: cz-shortcut-listen
Warning: Extra attributes from the server: data-new-gr-c-s-check-loaded,data-gr-ext-installed
A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up.

A Grammarly hydration error is one example. cz-shortcut-listen="true"? Next.js did not add that attribute; check ColorZilla on <body>.

Attribute or elementAdded by
data-new-gr-c-s-check-loaded, data-gr-ext-installed, <grammarly-desktop-integration>Grammarly
cz-shortcut-listen="true"ColorZilla
data-lt-installedLanguageTool
bis_skin_checkedCommonly traced to Bitdefender's browser extension
Their own data-* attributes on forms and inputsPassword managers such as LastPass, Dashlane and 1Password
data-darkreader-* and inline stylesDark Reader
__gchrome_uniqueid on inputsChrome and Edge on iPad, not an extension

The __gchrome_uniqueid hydration warning can come from Chrome or Edge on iPadOS, not an extension (Next.js issue). Confirm it the same way before adding an ignore rule.

hydration-proof reports recognized extension changes as HP4002, an informational finding by default. Other pre-hydration changes appear as HP4001.

Why a browser extension hydration error happens

An extension can mark <body>, modify an input, or insert an element before your app starts. React compares against that changed DOM, not just the server response.

React 19 tolerates some extra tags, but changed attributes or text can still mismatch. A script inserted before <head> can also break hydration (React issue).

How to fix it

Do not change app code until you have confirmed the extension caused it.

Confirm it in a clean profile

  1. Open the page in a private window with extensions disabled, or in a new browser profile.
  2. Reload with the console open. If the warning is gone, an extension caused it.
  3. Turn extensions back on one at a time to find which one, if you need to know.

If the warning stays in a clean profile, inspect your app and its third-party scripts.

Silence the development warning on html and body only

If an extension changes an attribute on <body> or <html>, you can put suppressHydrationWarning on that element during development:

app/layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body suppressHydrationWarning>{children}</body>
    </html>
  );
}

This covers only that element's own attributes. It does not cover inputs or text below it. See suppressHydrationWarning before using it elsewhere.

Catch it with ESLint

A linter cannot see browser extensions. The audit-suppress-hydration-warning rule checks where you use React's suppression prop.

Catch it in CI

hydration-proof test uses a clean browser, so extensions in your everyday profile do not affect it. If you simulate one with a scenario's initScripts, recognized changes appear as HP4002. To ignore a confirmed attribute, name it in the config:

hydration-proof.config.ts
import { defineConfig } from "hydration-proof";
 
export default defineConfig({
  ignore: {
    attributes: ["cz-shortcut-listen", /^data-gr-/],
  },
});

Ignored findings remain visible in the report. See ignoring findings.