hydration-proof checks your server-rendered React pages in a real browser. Run
npx hydration-proof test to see where the server HTML differs from React's
first client render, along with the values, likely cause, and a fix.
Install hydration-proof
Add it as a dev dependency, then download the browser once:
npm install -D hydration-proof
npx hydration-proof install # downloads ChromiumYou need Node.js 22.18 or newer. npm, pnpm, Yarn (including Plug'n'Play), and
Bun are supported. Installing the package does not download a browser;
hydration-proof install does that when you run it.
To catch the same mistakes in your editor, add the ESLint plugin as well:
npm install -D eslint-plugin-hydration-proofRun your first test
npx hydration-proof init # creates hydration-proof.config.ts
npx hydration-proof testFor Next.js, React Router, Remix, and Astro apps, you can start with these commands. hydration-proof:
- discovers your routes from
app/,pages/and the build output, - builds the app if there is no build yet, and starts it on a free port,
- loads every route and compares the server HTML with the hydrated DOM,
- exits with code
1if it found a problem.
Vite SSR and custom Node servers are detected too. Any other setup works with
--url (see adapters).
Read the report
The terminal lists pages that need attention. Each finding shows the issue code, both values, a source line when available, and a suggested fix:
Hydration Proof — checking 20 pages on http://localhost:3000
✖ /dashboard 1.1s 1 error
HP1001 Text differs between server and client · app/dashboard/LastLogin.tsx:14
server "5:00 AM" → client "10:00 AM"
Possible cause: Timezone difference. Fix: Use the same timeZone on the server and client.
Pages tested: 20
Passed: 19
Failed: 1
Report: .hydration-proof/report/report.html
More detail: run with --verbose or open the report.HP1001is a stable issue code with its own page.Timezone differenceis a likely cause, not proof. Run with--probeto test it.
Open .hydration-proof/report/report.html for every finding, screenshots, and
the page timeline. Use --verbose to show all findings in the terminal too.
Reports covers every output format.
Test an app that is already running
npx hydration-proof test --url http://localhost:3000 --route / --route /pricingWith --url, nothing is built or started, and only the routes you name are
tested. Add --sitemap to test the pages in your sitemap, or --crawl to
follow links from the tested pages.
Test development and production builds
Development builds give exact source lines. Production builds show what your users get, including attribute mismatches React 19 never reports in production. Test both in one run:
npx hydration-proof test --mode bothAdd it to CI
- run: npm ci
- run: npx hydration-proof install --with-deps
- run: npx hydration-proof testOr let npx hydration-proof init --ci github write the workflow for you.
Detect hydration errors in CI covers GitHub Actions, GitLab and
CircleCI, sharding, baselines and budgets.
Configure it
init creates a small config. Keep it as-is unless your app needs a setting
the tool cannot discover, such as a real ID for a dynamic route:
import { defineConfig } from "hydration-proof";
export default defineConfig({
routes: {
dynamic: { "/products/[id]": ["your-stable-test-product-id"] },
},
});Replace the sample ID with one that exists in your test data. See configuration for other options and scenarios for signed-in pages.
Related
- How hydration-proof works: the six snapshots it compares
- What is hydration in React?
- All React hydration error messages, decoded
- Common causes of hydration errors and their fixes
- The CLI: every command and flag