# Extra attributes from the server

> Warning: Extra attributes from the server means the page had attributes React did not render, often class and style from next-themes or a browser extension.

Source: https://hydration.jscrate.dev/docs/errors/extra-attributes-from-the-server
Last updated: 2026-09-18

"Extra attributes from the server" is a React 18 development warning: an
element has attributes that React's first client render does not produce.
Usually something changed the HTML before React loaded: a theme script that
adds `class` and `style` to `<html>`, or a browser extension that marks
`<body>`. It is a warning, not a failed hydration.

## The error

React 18 lists the attribute names, separated by commas:

```text
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 under it ends at the element, often `at body` or
`at html`. Production builds do not check attributes, so there is no minified
code.

React 19 dropped the separate warning. The same attributes appear as `-`
lines in the diff of
["A tree hydrated but some attributes… didn't match"](https://hydration.jscrate.dev/docs/errors/tree-hydrated-but-attributes-didnt-match),
for example `- cz-shortcut-listen="true"`.

## What extra attributes from the server means

React 18 compares the attributes of each hydrated element with the props you
rendered. Attributes that exist in the page but not in your props are "extra".
React does not remove them and does not render the page again: it logs the
warning once and continues.

The name is misleading. "From the server" means "in the DOM React found",
which includes anything a script or an extension added after the HTML
arrived. Your server often never sent these attributes.

## Common causes

| Attribute                                               | Added by                                               | What to do                                                                            |
| ------------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------- |
| `class`, `style` on `<html>`                            | next-themes or your own theme script, before hydration | Add `suppressHydrationWarning` to `<html>`. See [theme](https://hydration.jscrate.dev/docs/causes/theme)           |
| `cz-shortcut-listen` on `<body>`                        | The ColorZilla extension                               | Nothing in your code. See [extensions](https://hydration.jscrate.dev/docs/causes/extension)                        |
| `data-new-gr-c-s-check-loaded`, `data-gr-ext-installed` | Grammarly                                              | Nothing in your code                                                                  |
| Other `data-*` or `style`                               | A/B testing, analytics or chat scripts                 | Load them after hydration. See [third-party scripts](https://hydration.jscrate.dev/docs/causes/third-party-script) |
| Attributes on many elements                             | A CDN or proxy rewriting HTML                          | Turn the rewriting off. See [CDNs](https://hydration.jscrate.dev/docs/causes/cdn)                                  |

Extensions are a known problem with no fix on React's side yet: React issue
[#24430](https://github.com/facebook/react/issues/24430) about them is still
open.

## How to fix it

1. **Read the attribute names** and decide who added them, using the table.
2. **Test in a private window or a clean browser profile.** If the warning
   disappears, an extension added the attribute. Your users will see it too,
   but nothing is broken.
3. **For a theme script, mark `<html>` as expected to differ.** next-themes
   sets `class` and `style` on `<html>` before React loads, on purpose, to
   avoid a flash of the wrong theme:

   ```tsx title="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>
     );
   }
   ```

   `suppressHydrationWarning` covers only the element's own attributes and
   text, one level deep, so mismatches inside the page are still reported.

4. **For extensions on `<body>`,** you can add `suppressHydrationWarning` to
   `<body>` to silence them in development. It hides your own `<body>`
   attribute differences too, so keep it off `<body>` if you set attributes
   there. See [when suppressHydrationWarning is safe](https://hydration.jscrate.dev/docs/guides/suppresshydrationwarning).
5. **For scripts,** load them after hydration so they change the page once
   React owns it.

## Find every instance

hydration-proof reports an attribute that only the page has as
[HP1005](https://hydration.jscrate.dev/docs/issues/hp1005). When it can tell that a script or extension
added it before hydration, it reports [HP4001](https://hydration.jscrate.dev/docs/issues/hp4001) or
[HP4002](https://hydration.jscrate.dev/docs/issues/hp4002) instead:

```bash
npx hydration-proof test
```

The test browser runs without extensions. If you simulate one, or if your
own scripts add attributes on purpose, skip those attributes in the config:

```ts title="hydration-proof.config.ts"
import { defineConfig } from "hydration-proof";

export default defineConfig({
  ignore: {
    attributes: ["cz-shortcut-listen", /^data-gr-/],
  },
});
```

[`audit-suppress-hydration-warning`](https://hydration.jscrate.dev/docs/rules/audit-suppress-hydration-warning)
reviews every `suppressHydrationWarning` you add, so none of them hides more
than intended. [Ignoring findings](https://hydration.jscrate.dev/docs/ignoring) covers the other options.

## Related

- [Browser extensions that cause hydration errors](https://hydration.jscrate.dev/docs/causes/extension)
- [The next-themes hydration warning](https://hydration.jscrate.dev/docs/causes/theme)
- [Prop className did not match](https://hydration.jscrate.dev/docs/errors/prop-classname-did-not-match)
- [suppressHydrationWarning explained](https://hydration.jscrate.dev/docs/guides/suppresshydrationwarning)
- [HP1005: attribute only present in the server HTML](https://hydration.jscrate.dev/docs/issues/hp1005)
