Hydration Proof

Search documentation

Find a page or section

Extra attributes from the server

React 18's warning for attributes that something else added.

"Extra attributes from the server" means React 18 found DOM attributes that the first browser render did not produce. Check the attribute names. A theme script or browser extension may have added them before hydration; your server may not have sent them at all.

The error

React 18 names the extra attributes:

Warning: Extra attributes from the server: class,style
Warning: Extra attributes from the server: style
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

The component stack points to the element, often <body> or <html>. There is no matching minified production code for this warning.

React 19 includes these differences in its broader attribute warning: "A tree hydrated but some attributes… didn't match", for example - cz-shortcut-listen="true".

What extra attributes from the server means

"Extra" means the attribute exists in the DOM but not in React's rendered props. React warns and may leave the DOM attribute in place.

The wording can mislead: the attribute may have come from a script or extension after the server response arrived.

Common causes

AttributeAdded byWhat to do
class, style on <html>next-themes or your own theme script, before hydrationAdd suppressHydrationWarning to <html>. See theme
cz-shortcut-listen on <body>The ColorZilla extensionNothing in your code. See extensions
data-new-gr-c-s-check-loaded, data-gr-ext-installedGrammarlyNothing in your code
Other data-* or styleA/B testing, analytics or chat scriptsLoad them after hydration. See third-party scripts
Attributes on many elementsA CDN or proxy rewriting HTMLTurn the rewriting off. See CDNs

See the React issue for discussion of extension-added markup.

How to fix it

  1. Identify the attribute using the table above.

  2. Try a clean browser profile. If the warning disappears, check your extensions rather than changing app code.

  3. For a theme script, mark <html> as expected to differ:

    app/layout.tsx
    import { ThemeProvider } from "next-themes";
    import type { ReactNode } from "react";
     
    export default function RootLayout({ children }: { children: ReactNode }) {
      return (
        <html lang="en" suppressHydrationWarning>
          <body>
            <ThemeProvider attribute="class">{children}</ThemeProvider>
          </body>
        </html>
      );
    }

    The prop covers <html> itself, not the rest of the page.

  4. For a confirmed extension attribute on <body>, you may suppress its development warning. Be aware that this hides other <body> attribute differences too. See suppression limits.

  5. For your own scripts, stop them from changing React-owned markup before it hydrates.

Find every instance

hydration-proof reports a server-only attribute as HP1005. If a script or extension added it before hydration, the report may show HP4001 or HP4002:

npx hydration-proof test

The test browser has no extensions. To exclude a confirmed attribute added by a script or simulated extension, list it in the config:

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

audit-suppress-hydration-warning checks suppression placement. See ignoring findings for test-only exceptions.