How to Detect Next.js and React on a Website
React is a UI library and Next.js is a framework built on it, so the signs overlap but are not the same. This guide separates them, lists the markers for the Pages Router and the App Router, and explains why detection is less certain than for a CMS.
React is a library, Next.js is a framework
React renders user interfaces from components. It does not decide how pages are routed, how data is fetched on the server or how the code is bundled. Next.js, made by Vercel, adds those decisions: file-based routing, server-side rendering, static generation, API routes and an optimised build. A site built with Next.js is also a React site. A React site is not necessarily Next.js; it might be a single-page app made with Vite or Create React App, a Remix or Gatsby site, or a plain React widget embedded in an otherwise ordinary page.
For detection this means you work from the specific to the general: look for framework markers first, then for React itself.
Next.js markers in the HTML
- Script and style paths under
/_next/. Build output is served from/_next/static/, for example chunks in/_next/static/chunks/. Optimised images are requested from/_next/image?url=.... This is the strongest single marker, and it survives most customisations because the framework expects it. A configurableassetPrefixcan move static files to a CDN host, but the/_next/static/segment usually remains in the path. - A root element with the id
__next. Pages Router applications mount into this element. - A
script id="__NEXT_DATA__" type="application/json"element. The Pages Router serialises page props there so that the browser can hydrate. Reading it shows the page route, build ID and props. Be aware that it can contain whatever data the page used, so look at it only for the structure, not the content. - The App Router. Newer applications that use the App Router do not use
__NEXT_DATA__. Instead they embed React Server Components payload chunks through inline scripts callingself.__next_f.push, and still serve assets from/_next/static/. - Meta tag. Some Next.js pages include
<meta name="next-head-count">, a marker of older Pages Router versions.
Next.js markers in headers and behaviour
X-Powered-By: Next.jsis added by default in self-hosted setups. Many deployments disable it via thepoweredByHeaderoption, and Vercel hosting adds its own headers such asx-vercel-id.- A response header
x-nextjs-cachemay report HIT or MISS for statically generated pages in some versions. - Prefetch requests: in DevTools, navigating between pages loads small JSON or RSC responses on hover or on link visibility, rather than full documents. This indicates client-side routing in a React framework.
React markers
| Signal | Meaning | Reliability |
|---|---|---|
data-reactroot attribute | Server-rendered React before version 18 | High for older sites; React 18 and later no longer add it |
__REACT_DEVTOOLS_GLOBAL_HOOK__ on window | Present when the React DevTools extension is installed, even on non-React pages | Not a site signal; ignore it |
Elements with keys starting __reactFiber$ or __reactProps$ | React attached internal data to DOM nodes (readable in the console) | High, but only with JavaScript access |
Bundle file names such as react-dom or a main.*.js built by a React toolchain | React bundles; names vary | Medium |
A near-empty body with a single div id="root" | Client-side rendered single-page app | Medium; also true of other frameworks |
The framework test is easier in a browser than in a raw HTTP fetch, because React's internal markers are attached when the code runs. A crawler that only fetches HTML sees the server-rendered markup and the script tags, which is why server-rendered Next.js is detected so reliably by path while client-only React apps are harder.
Other frameworks that look similar
Do not assume that every modern site is Next.js. Nuxt, the Vue equivalent, uses /_nuxt/ and a __NUXT__ global. Gatsby uses a ___gatsby root. Remix and React Router use their own hydration data scripts. SvelteKit uses /_app/immutable/ paths. Astro emits astro-island custom elements. A quick glance at the asset path prefix usually distinguishes them. Pair that with the CMS checks in what CMS a website uses, because a decoupled site may run Next.js in front of WordPress, a hosted headless CMS or a commerce API.
Detecting the host
Next.js is often hosted on Vercel, but also on Netlify, Cloudflare, AWS or ordinary servers. Header hints like x-vercel-id identify the host, while the edge may be a general CDN, as discussed in Cloudflare and CDN detection. Separating framework, host and CDN gives a correct stack description: for instance "Next.js on Vercel, behind its own edge network".
Why it matters
- Developer hiring and agency targeting. The framework tells you which skills a site's maintainers need.
- Technical SEO. Server-rendered and static pages are easy for crawlers; client-only apps can need extra care for indexing.
- Security triage. Framework version matters when a vulnerability is announced. A detector with version patterns, such as the ones in Lens's catalogue, can help to find which sites might be affected, but hardened sites often hide versions.
- Market research. Whether new sites choose a JavaScript framework or a hosted builder is a recurring question, which the live data on /technologies helps to answer for the sites observed.
A console recipe
- Open DevTools, then the Elements tab, and search for
__nextand_next/static. - In the console, run
!!document.getElementById('__NEXT_DATA__')for the Pages Router, andtypeof self.__next_ffor the App Router. - Check the response headers for
x-powered-byandx-vercel-id. - If none of this matches, look for other framework prefixes before deciding it is custom React.
The TLDlive Lens catalogue performs the equivalent checks on every page you visit and lists React, Next.js and related tooling in the popup. See technology fingerprinting and privacy for how that happens without collecting page content.
Sources
- Next.js documentation, including
poweredByHeaderand asset prefix configuration: nextjs.org/docs - React documentation: react.dev
- Vercel documentation, headers reference: vercel.com/docs
- Nuxt and SvelteKit documentation for their asset directories: nuxt.com, svelte.dev
Frequently asked questions
How do I check if a website uses Next.js?
Look in the page source for requests to /_next/static/ and a __next root or a __NEXT_DATA__ script. Pages built with the App Router use self.__next_f instead of __NEXT_DATA__ but still load assets from /_next/static/.
Does Next.js always send an X-Powered-By header?
By default self-hosted Next.js sends X-Powered-By: Next.js, but the setting can be turned off and some hosts remove or override headers, so absence proves nothing.
Can I tell the React version?
Sometimes. Bundle comments, a global version string or a detector's version pattern can reveal it, but production builds often hide it. Treat an unknown version as normal.
Is every site with /_next/ in its URLs hosted on Vercel?
No. Next.js can be hosted anywhere that runs Node.js or a compatible edge runtime. Hosting is determined by headers and DNS, not by the framework markers.