How to check if a website is built with Next.js
Next.js is built in a way that makes it hard to hide. The framework inserts a `#__next` wrapper, a `__NEXT_DATA__` JSON script, and loads every route chunk from `_next/static/`. One glance at DevTools is enough.
Background
Next.js has two active router paradigms (Pages Router, around since v9; App Router, since v13) and both leave distinctive traces in the page's output. Pages Router apps are easy — `#__next` wrapper, `__NEXT_DATA__` JSON script, `/_next/static/chunks/pages/_app-<hash>.js` script URL. App Router apps are slightly trickier: no `#__next` wrapper, no `__NEXT_DATA__`, just RSC flight payloads pushed via `self.__next_f.push(...)` and chunks under `/_next/static/chunks/app/`. Both share the `/_next/static/` prefix, which is the most reliable single signal. Add the `X-Powered-By: Next.js` response header on the document (present on most self-hosted setups, stripped on some CDN-fronted ones), and the identification is usually unambiguous. Getting the exact version takes one more step — either reading `X-Powered-By` if it's present with a version, or reading `node_modules/next/package.json` from the sourcemap.
Why this matters
Next.js is one of the most-used production React frameworks. Knowing a site is on Next.js tells you: it's SSR-capable, likely hosted on Vercel (but not necessarily), probably using the latest React, likely paired with Tailwind and shadcn/ui, and subject to specific ISR/streaming behaviors that affect how you should test its performance. It also narrows down what else to look for — NextAuth, Prisma, tRPC, SWR, TanStack Query are common companions.
Prerequisites
- Chrome DevTools access.
- Basic familiarity with the Network and Elements panels.
Step-by-step
- 1
Check for #__next in the DOM
Open DevTools → Elements → search for `__next`. If you see `<div id="__next">` or `<div id="__next__">`, the site is a Next.js Pages Router app. App Router apps won't have that div but will still have `__NEXT_DATA__`.
- 2
Look for __NEXT_DATA__ script
In the Elements panel, search for `__NEXT_DATA__`. You'll find a `<script id="__NEXT_DATA__" type="application/json">` with page props and the build ID. App Router uses a streamed flight payload instead — look for `self.__next_f.push` in inline scripts.
Tip: `__NEXT_DATA__` has a `buildId` field — a hash of the current deployment. Different `buildId`s on reload means the site was redeployed between your visits.
- 3
Inspect asset URLs
Every Next.js app loads chunks from `/_next/static/chunks/` and CSS from `/_next/static/css/`. If you see those paths in the Network tab, it's Next.js. The chunk subdirectory tells you the router: `/_next/static/chunks/pages/` (Pages Router) vs `/_next/static/chunks/app/` (App Router).
- 4
Check response headers
`X-Powered-By: Next.js` (often with version), `X-Nextjs-Cache`, `X-Nextjs-Matched-Path`. Vercel hosts usually add `X-Vercel-Id` alongside.
Tip: `X-Nextjs-Cache: HIT` indicates an ISR-cached page; `MISS` means server-rendered on the request; `REVALIDATED` means the cache was refreshed for this request.
- 5
Get the exact version via Sourcemap Explorer
If the site ships sourcemaps (most Next.js apps do by default), Sourcemap Explorer will read `node_modules/next/package.json` from the map and show the exact version — e.g. Next.js 14.2.3 — instead of the coarse major number some detectors report.
Real-world example
Troubleshooting
I see `_next/static/` but no `__NEXT_DATA__`.
You're on an App Router page. Look for `self.__next_f.push(...)` in inline scripts — that's the RSC flight payload, which replaces `__NEXT_DATA__` in App Router.
No `X-Powered-By` header.
Admin-stripped for security theater. The `_next/static/` path prefix is your confirmation; it can't be stripped without breaking the app.
Caveats
What to do next
Once you've confirmed Next.js, the usual follow-ups are identifying the exact React version, detecting any CMS behind it (headless WordPress, Sanity, Contentful), and enumerating the UI kit and data layer (Tailwind, shadcn/ui, TanStack Query, SWR). Related guides cover each.
FAQ
Can I tell App Router from Pages Router?
App Router apps have no `#__next` wrapper and no `__NEXT_DATA__` script; they stream RSC payloads via `self.__next_f.push(...)` in inline scripts. Pages Router apps have both. Sourcemap Explorer surfaces this distinction when the sourcemap is available.
How do I tell what version of Next.js is running?
The `X-Powered-By` header often includes it. Failing that, if sourcemaps are exposed, `node_modules/next/package.json` inside the map has the exact `version` field. Sourcemap Explorer reads it automatically.
Is every Vercel site a Next.js site?
No. Vercel hosts many frameworks — Remix, SvelteKit, Astro, plain static sites. The `X-Vercel-Id` header only confirms hosting; the `_next/static/` chunk path confirms Next.js.
Can a site fake being Next.js?
Theoretically yes, but no one does. The fingerprint combination is too deep to spoof without actually running Next.js.
Related
Skip the manual steps.
Sourcemap Explorer automates every workflow in this guide — free, local, no sign-up.