A next/script hydration error can happen when a script changes the DOM before React hydrates it. Tag managers, experiments, and consent tools may rewrite text or add elements. Keep those changes outside React's tree, or run them only after the affected content has hydrated.
Symptoms
Hydration failed because the server rendered text didn't match the client.
Warning: Text content did not match. Server: "Hello world" Client: "Hola mundo"
Warning: Extra attributes from the server: data-experiment
Minified React error #418; visit https://react.dev/errors/418The error may come and go because script and hydration timing varies.
hydration-proof reports a pre-hydration change as HP4001 and shows both values:
HP4001 The page was modified before React hydrated · #greeting
server "Hello world" → client "Hola mundo"
Possible cause: A script changed the page before hydration. Fix: Load it after hydration or keep it outside React's tree.Why the next/script hydration error happens
React hydrates the DOM as it exists at that moment. Scripts that run between HTML parsing and hydration can change it:
- scripts in
<head>withoutdeferorasync, and inline scripts next/scriptwithstrategy="beforeInteractive", which Next.js injects into the<head>of the server HTML and fetches before any Next.js code- tag managers and experimentation tools that swap text or classes as early as they can, to avoid a flash
- personalization, translation and consent tools that edit the page on load
next/script beforeInteractive hydration error
beforeInteractive scripts load early. If they edit React-owned DOM, they
can race hydration. Use this strategy for scripts that must run early and do
not change that DOM. See the Next.js issue
for a reported case.
next/script nonce CSP hydration warning
With a Content Security Policy that uses a nonce, you may see:
Warning: Extra attributes from the server: nonceBrowsers hide a parsed script's nonce attribute from normal DOM reads, even
though the nonce still controls whether it runs
(React issue). Do not expose
the nonce to client code just to silence a warning. Follow the
Next.js CSP guide.
Vercel Speed Insights hydration error
A Vercel Speed Insights hydration error was reported in a Next.js issue. If you see a similar error, check your package versions, then test whether the DOM changed before hydration or the component itself rendered differently.
How to fix it
Load the script after hydration
afterInteractive runs after some hydration, not necessarily after every
component hydrates. lazyOnload waits until browser idle time. Neither is a
license to rewrite React-owned markup; use a later hook if the target must be
hydrated first:
import Script from "next/script";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
{children}
{/* Before: strategy="beforeInteractive" */}
<Script
src="https://example.com/experiments.js"
strategy="afterInteractive"
/>
<Script
src="https://example.com/chat-widget.js"
strategy="lazyOnload"
/>
</body>
</html>
);
}Use the latest loading strategy your script can tolerate, and test the route under slow-network conditions.
Give the script its own element
If a script must run early, give it a separate container outside the React root when possible. Avoid changing a placeholder React expects to hydrate.
Move experiments to the server
For an A/B test, choose the variant on the server and pass that decision to the browser. See server and client data.
Mark inline theme scripts
For a theme script that changes only <html>, use the focused pattern in the
theme guide.
Catch it with ESLint
A linter cannot inspect what an external script does at runtime. Test the page in a browser.
Catch it in CI
hydration-proof compares parsed server HTML with the DOM before React
hydrates. It reports script changes as HP4001 and recognized extension changes
as HP4002. Use a scenario's initScripts to test a
script before shipping it. See how it works.
npx hydration-proof test