Skip to content

SPA, SSR and hydration

Reading Next.js hydration data without a browser

Next.js pages often ship their content as JSON in the first response. Where to find __NEXT_DATA__ and the App Router payload, and how to parse them safely.

Published

This article was drafted with AI assistance from the sources listed below and edited and published by Teneo Labs.

From a Next.js page to its data
  1. 1Fetch the raw HTMLNo browser. One request.
  2. 2Find the payload__NEXT_DATA__ (Pages Router) or self.__next_f (App Router).
  3. 3Parse and check the shapeFail loudly when expected fields are missing.
  4. 4Compare with the visible textThe page wins when the two disagree.

A Next.js page that looks empty to a plain fetch often is not empty at all. When the page is rendered on the server or at build time, Next.js embeds the data it used, so the browser can hydrate without asking again. For a reader, that embedded data is often the cleanest source on the page.

Where it lives depends on the router.

Pages Router: __NEXT_DATA__

Pages that use the Pages Router, including those with getServerSideProps or getStaticProps, include a script tag like this:

<script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{...}},"page":"/blog/[slug]", ...}</script>

The Next.js docs describe how getServerSideProps returns props that the page renders with; those props end up in this script. It is plain JSON, so any language can parse it:

import json, re, requests

html = requests.get("https://example.com/", timeout=30).text
m = re.search(r'<script id="__NEXT_DATA__" type="application/json"[^>]*>(.*?)</script>', html, re.S)
if not m:
    raise SystemExit("no __NEXT_DATA__ on this page")
data = json.loads(m.group(1))
props = data.get("props", {}).get("pageProps")
if not props:
    raise SystemExit("payload found, but pageProps is empty")
print(sorted(props.keys()))

example.com is not a Next.js site, so this prints "no NEXT_DATA on this page". Point it at a Pages Router page you are allowed to read and the keys show what the page renders.

App Router: the RSC payload

App Router pages use React Server Components. The Next.js docs explain that the server renders Server Components into a special data format, the RSC payload, which the client uses to build the page. In the HTML it appears in inline scripts:

curl -sL https://example.com/ | grep -c 'self.__next_f.push'

The payload is a stream of lines, not one JSON document, so there is no stable way to parse it fully. In practice, two things work: the visible text is usually already in the server-rendered HTML, so read that first; and string fields such as titles are often findable with a targeted search. Treat anything more as fragile.

Rules that keep this safe

  • It is an implementation detail. Field names follow the site's code, not a public API. Validate the shape and alert when it changes.
  • Use what the page publishes. Hydration data can include fields the page does not show. Read what the page displays, ignore anything that looks private, and respect robots.txt and the site's terms.
  • The page wins. If the payload and the visible text disagree, trust the text and log the mismatch.

The SPA, SSR and hydration guide lists where Nuxt, SvelteKit, Remix and Astro keep the same kind of data.

Test it yourself

Run the regex above on a Next.js page you use. If it finds pageProps, compare three fields with what you see on screen. If it finds nothing, check for self.__next_f and then for text in the plain HTML before you decide the page needs a browser.

Frequently asked questions

What is __NEXT_DATA__?

A script tag with id __NEXT_DATA__ and type application/json that Next.js Pages Router pages include so the client can hydrate. It holds the page props, among other fields, as plain JSON.

Do App Router pages have __NEXT_DATA__?

No. App Router pages send the React Server Components payload in inline scripts that call self.__next_f.push. It is not plain JSON, but text and props are often readable in it.

Sources

  1. getServerSideProps (Next.js docs) (Documentation)
  2. Server and Client Components (Next.js docs) (Documentation)