Hydration Proof

Search documentation

Find a page or section

Install it, test your app, and read the result.

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 Chromium

You 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-proof

Run your first test

npx hydration-proof init  # creates hydration-proof.config.ts
npx hydration-proof test

For Next.js, React Router, Remix, and Astro apps, you can start with these commands. hydration-proof:

  1. discovers your routes from app/, pages/ and the build output,
  2. builds the app if there is no build yet, and starts it on a free port,
  3. loads every route and compares the server HTML with the hydrated DOM,
  4. exits with code 1 if 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.
  • HP1001 is a stable issue code with its own page.
  • Timezone difference is a likely cause, not proof. Run with --probe to 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 /pricing

With --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 both

Add it to CI

.github/workflows/hydration.yml
- run: npm ci
- run: npx hydration-proof install --with-deps
- run: npx hydration-proof test

Or 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:

hydration-proof.config.ts
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.