Detect Nuxt JS Website: 5 Signals and a Free API Call
Just want the answer? Run curl -s "https://detectzestack.com/demo?url=nuxt.com" — no API key, no signup. Or use the free Framework Detector. The article below explains every signal behind that answer and when each one lies to you.
A framework detector that tells you a site uses Vue.js has told you almost nothing. Vue is the rendering layer; the interesting question is what is sitting on top of it, because that determines the build pipeline, the hosting shape, the hiring profile, and whether the team is running a server at all.
Nuxt is the answer most of the time, and it leaves specific, durable fingerprints in server-rendered HTML. Running about.gitlab.com through the detection API returns both at once:
"JavaScript frameworks": [
"Nuxt.js",
"Vue.js"
]
This guide covers the five signals that separate a Nuxt site from a plain Vue site, how Nuxt’s three rendering modes change what you can see from the outside, the exact curl commands, and the three failure modes that produce a false negative.
Why Nuxt.js Detection Is Different From Vue.js Detection
Vue.js fingerprints are generic on purpose: data-v- scoped-style attributes emitted by single-file components, a Vue global on the window object, and vue.min.js in a script URL when the library comes from a CDN. Those appear on every Vue application, including every Nuxt application, so finding them narrows nothing.
Nuxt adds markers no plain Vue app produces. It controls the HTML document, the build output path, and the hydration payload, and all three carry its name — which is what makes Nuxt detectable from a single unauthenticated HTTP fetch, with no headless browser and no JavaScript execution.
The relationship also runs one way in the fingerprint data. Nuxt.js implies both Vue.js and Node.js, so a confirmed Nuxt detection pulls both into the response even when nothing in the HTML independently proves Vue. Detecting Vue implies nothing about Nuxt. If you are building a filter, filter on Nuxt.js and accept Vue.js as a passenger — not the other way around.
One more quirk worth knowing before you write a category filter: Nuxt.js is classified under four categories at once, because it genuinely is all four things.
| Category | Why Nuxt is filed here |
|---|---|
| JavaScript frameworks | The Vue-based component layer |
| Web frameworks | Routing, data fetching, middleware |
| Web servers | The Nitro server that handles SSR requests |
| Static site generator | Prerender mode, which emits plain HTML files |
A query filtering on categories["Static site generator"] will therefore return SSR-mode Nuxt sites that generate nothing statically. Match on the technology name, not the category, when you need precision.
The Five Signals That Identify a Nuxt Site
1. The __nuxt Mount Element (Nuxt 3/4) vs the __NUXT__ Global (Nuxt 2)
Nuxt mounts the application into a div with a fixed id. It is the first thing to grep for:
$ curl -s https://nuxt.com | grep -o 'id="__nuxt"[^>]*'
id="__nuxt" class="isolate"
$ curl -sL https://about.gitlab.com | grep -o 'id="__nuxt"'
id="__nuxt"
The second marker is the window.__NUXT__ global. In Nuxt 2 this held the entire serialized application state and was the canonical fingerprint. In Nuxt 3 and 4 it still exists, but its job shrank to carrying runtime config — the hydration data moved to a separate script (signal 3). Here is what nuxt.com actually emits:
<script>window.__NUXT__={};window.__NUXT__.config={public:{...}}</script>
Both forms survive an HTTP fetch because they are written into the server response, not created at runtime. That is the whole reason Nuxt is detectable without a browser.
2. /_nuxt/ Hashed Asset Paths in the HTML Source
Every Nuxt build writes its JavaScript and CSS bundles under a /_nuxt/ directory with content-hashed filenames. Those URLs are referenced directly in the page source:
$ curl -s https://nuxt.com | grep -o '/_nuxt/[A-Za-z0-9._-]*' | sort -u | head -4
/_nuxt/0cZM9QsX.js
/_nuxt/0K6Znzx6.js
/_nuxt/2lngBEtA.js
/_nuxt/AgentNuxiIcon.CWc0ZLtP.css
This is the highest-volume signal — a real page emits dozens of these — which makes it the most robust to partial fetches and truncated responses. It is also the one signal a team can turn off, via the buildAssetsDir option that relocates the directory. Almost nobody changes it, but that is why you should not build a detector on this signal alone.
The path survives a CDN. Both nuxt.com (behind Vercel) and about.gitlab.com (behind Cloudflare) still reference /_nuxt/, because it is baked into the HTML at build time and the CDN is only caching the result.
3. The Serialized Payload Script (__NUXT_DATA__ and _payload.json)
This is the signal most guides miss, and it is the one that tells you the most. Nuxt 3 and 4 serialize hydration state into a JSON script tag and separately expose it as a fetchable file. Real markup from nuxt.com:
<link rel="preload" as="fetch" crossorigin="anonymous"
href="/_payload.json?_b=747e347f-e406-40d0-b41a-3d85bb5ee91e">
<script type="application/json" data-nuxt-data="nuxt-app" data-ssr="true"
id="__NUXT_DATA__" data-src="/_payload.json?_b=747e347f-...">
[{"state":1,"once":...}]
</script>
Three confirmations live in that one tag. id="__NUXT_DATA__" and data-nuxt-data="nuxt-app" are Nuxt-specific strings that appear nowhere else, data-src confirms the payload route, and data-ssr="true" tells you the page was server-rendered rather than shipped as a client-only shell — a rendering-mode readout for free, without a second request. about.gitlab.com emits the identical structure with its own cache-busting token, which confirms this is framework output rather than a per-site choice.
4. Server Response Headers: The Signal Nuxt Does Not Send
Plenty of framework-detection advice tells you to check X-Powered-By. For Nuxt, that advice is wrong, and it is worth being blunt about it because chasing a header that does not exist is how people conclude a Nuxt site is not a Nuxt site.
Nitro, the server engine that powers Nuxt 3 and 4, does not brand its responses. Checking three confirmed Nuxt sites in September 2026:
| Site | Server header | X-Powered-By |
|---|---|---|
| nuxt.com | Vercel | absent |
| ui.nuxt.com | Vercel | absent |
| about.gitlab.com | cloudflare | absent |
No Nitro header, no X-Powered-By, nothing framework-shaped at all. What the Server header tells you is who is in front of the origin — Vercel, Cloudflare, Netlify — which is useful infrastructure intelligence but says nothing about the framework. Treat headers as a source for the hosting half of the picture and read the HTML body for the framework half.
5. Co-Signals: Vue.js, Node.js, and the Hosting Platform
A confirmed Nuxt detection never arrives alone. Here is the complete live result for nuxt.com:
HSTS, Let's Encrypt, Node.js, Nuxt.js, Vercel, Vue.js
Vue.js and Node.js come from the implication chain. Vercel, HSTS, and Let’s Encrypt come from independent HTTP, header, and TLS-certificate checks. The shape is a small stack, which is typical of a documentation site with no marketing layer bolted on.
about.gitlab.com returns eleven technologies for the same scan, and the difference is entirely the marketing stack:
Cloudflare, Dreamdata, Google Cloud, HSTS, HTTP/3, Marketo,
Node.js, Nuxt.js, OneTrust, Optimizely, Vue.js
That contrast is the practical value of co-signals. Nuxt.js plus a CDN plus a certificate authority is an engineering-led site. Nuxt.js plus Marketo plus Optimizely plus OneTrust is a company with a marketing operations team and a compliance requirement — a different buyer, a different budget, and a different reason to care.
Nuxt Rendering Modes Change What You Can See
Nuxt supports three rendering strategies, and each one changes how much survives into the HTML an HTTP client receives. This matters more than any individual signal.
Universal / SSR (the default). The Nitro server renders each request. All five signals are present, and data-ssr="true" appears in the payload script. This is the easy case.
Static / prerendered (SSG). The pages are rendered at build time into plain HTML files and served from a CDN. Detection is just as reliable, because the markers are baked into the files. nuxt.com is the proof: its response carries x-vercel-cache: HIT, meaning nobody ran a server for that request, and all five signals are still there.
SPA mode (ssr: false). This is the one that breaks detection. The server returns a near-empty shell and the framework builds the page after JavaScript runs. Nothing an HTTP fetch sees has to mention Nuxt. A real example: vuetifyjs.com returns a 3,300-byte HTML document with no id="__nuxt" and no /_nuxt/ references, and a scan of it returns only Cloudflare, Cloudflare Browser Insights, Google Cloud, and cdnjs — no framework of any kind. A 3 KB HTML response is itself the tell: it means the page is client-rendered, and you should reach for DevTools rather than curl.
Manual Detection in 30 Seconds
Three commands, in order of how much they prove:
$ curl -s https://nuxt.com | grep -c 'id="__nuxt"'
1
$ curl -s https://nuxt.com | grep -o '/_nuxt/' | head -1
/_nuxt/
$ curl -s https://nuxt.com | grep -o '__NUXT_DATA__'
__NUXT_DATA__
Add -L whenever the apex domain might redirect — curl -sL https://about.gitlab.com — and add a browser User-Agent if you get a 403.
In DevTools the equivalent is a console one-liner: document.getElementById('__nuxt') returns the mount element, and window.$nuxt or window.__NUXT__ returns the app object. The console works on SPA-mode sites where curl fails, because by then the framework has already booted.
Detect a Nuxt JS Website With the DetectZeStack API
Free Demo Call, No API Key Required
The /demo endpoint runs the same detection as the paid endpoint and needs no signup:
curl -s "https://detectzestack.com/demo?url=nuxt.com"
Piping that through jq gets you straight to the answer:
curl -s "https://detectzestack.com/demo?url=nuxt.com" \
| jq -r '.technologies[].name'
Authenticated GET /analyze With Your API Key
Same response shape as /demo, against your own quota and without the per-IP cap:
curl -s "https://detectzestack.com/analyze?url=https://about.gitlab.com" \
-H "X-API-Key: YOUR_KEY"
A one-line yes/no filter for a list of candidates:
curl -s "https://detectzestack.com/analyze?url=https://about.gitlab.com" \
-H "X-API-Key: YOUR_KEY" \
| jq -r 'if any(.technologies[]; .name == "Nuxt.js") then "nuxt" else "not nuxt" end'
Batch Detection Across a Domain List With POST /analyze/batch
Ten URLs per call, scanned concurrently, results returned in input order:
curl -s -X POST "https://detectzestack.com/analyze/batch" \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"urls":["https://nuxt.com","https://about.gitlab.com","https://vuejs.org"]}'
The response wraps the per-URL results with successful, failed, and total_ms counters. Each entry in results has a url and a result holding exactly the object /analyze returns, so the same jq filter works one level deeper:
... | jq -r '.results[]
| select(.result.technologies[]?.name == "Nuxt.js")
| .result.domain'
For lists longer than ten domains, chunk them — see Batch Scan 1,000 Websites for the full pattern including retries and rate-limit handling.
Comparing Two Sites Side by Side With POST /compare
/compare takes between 2 and 10 URLs and returns, for each domain, the technologies unique to it, plus a shared array of everything common to all of them:
curl -s -X POST "https://detectzestack.com/compare" \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"urls":["https://nuxt.com","https://about.gitlab.com"]}'
Point it at a Nuxt site and a Next.js site and the unique arrays draw the line for you: Nuxt.js and Vue.js on one side, Next.js and React on the other, with Node.js sitting in shared because both meta-frameworks imply it.
What the API Response Actually Returns for a Nuxt Site
Here is the live /demo response for nuxt.com, trimmed to the Nuxt entry and the summary fields:
{
"url": "https://nuxt.com",
"domain": "nuxt.com",
"technologies": [
{
"name": "Nuxt.js",
"categories": [
"JavaScript frameworks",
"Web frameworks",
"Web servers",
"Static site generator"
],
"confidence": 100,
"description": "Nuxt is a Vue framework for developing modern web applications.",
"website": "https://nuxt.com",
"icon": "Nuxt.js.svg",
"source": "http"
}
],
"categories": {
"JavaScript frameworks": ["Vue.js", "Nuxt.js"],
"Programming languages": ["Node.js"],
"PaaS": ["Vercel"],
"Static site generator": ["Nuxt.js"],
"Web frameworks": ["Nuxt.js"],
"Web servers": ["Nuxt.js"],
"Security": ["HSTS"],
"SSL/TLS certificate authority": ["Let's Encrypt"]
},
"meta": {
"status_code": 200,
"tech_count": 6,
"scan_depth": "full"
},
"cached": true,
"response_ms": 0
}
Four fields deserve attention when you are writing code against this:
source: "http"— Nuxt was found in the HTTP response body. Other technologies in the same response carry"dns"or"tls". Nuxt will never be"dns", because there is no DNS record that reveals a JavaScript framework.confidence: 100— a full-confidence match from an unambiguous marker. Lower scores show up on inferred signals; in the nuxt.com response, Let’s Encrypt comes back at 70 because certificate-issuer inference is weaker evidence.categories— the grouped view. Note Nuxt.js appears under four keys and Vue.js under one, which is the four-category classification showing up in practice.cachedandresponse_ms— both top-level, not insidemeta. A cached hit returnsresponse_ms: 0; the only fields insidemetaarestatus_code,tech_count, andscan_depth.
Try it on your own list
100 requests per month on the free tier, no credit card. HTTP + DNS + TLS detection on every plan.
Get Your Free API KeyWhere Nuxt Detection Fails (and What to Do About It)
SPA mode returns a shell with nothing in it
Covered above, and it is the single largest source of false negatives. The diagnostic is response size: if the HTML is under roughly 5 KB and contains a lone empty div, the page is client-rendered and no HTTP-only detector will see the framework. Confirm with DevTools, or accept the gap. There is no way to recover this signal without executing JavaScript.
A bot-management challenge blocks the fetch
Scanning ecosia.org returns HTTP 403 with a 4 KB challenge page instead of the site. The scan is not wrong; it never got the HTML. You can usually tell this apart from a genuine negative by looking at what did come back — a result consisting only of edge-layer technologies such as Cloudflare, Cloudflare Bot Management, and HSTS, with no application-layer technologies at all, is the signature of a blocked fetch rather than a bare site.
The apex domain redirects somewhere else
Requesting gitlab.com follows a redirect to about.gitlab.com, and that is where Nuxt lives. Fetching the apex without -L would find nothing. The API follows redirects for you, but it reports the destination, so always read the domain field in the response rather than assuming it matches what you submitted. If you are joining results back to an input list, join on the URL you sent, not the domain you got.
A relocated build directory
The buildAssetsDir option moves assets off /_nuxt/. This removes one of the five signals, not all of them — the mount element and the payload script are unaffected — which is exactly why checking several markers beats checking one.
Detection Method Comparison
| Method | Sees SSR/SSG Nuxt | Sees SPA-mode Nuxt | Scales to a list |
|---|---|---|---|
| curl + grep | Yes | No | With scripting |
| DevTools console | Yes | Yes | No — one tab at a time |
| Browser extension | Yes | Yes | No — needs a human visit |
| Detection API | Yes | No | Yes — 10 URLs per batch call |
No single method wins. In-browser methods read the live DOM and catch client-rendered sites an HTTP fetch cannot, but they need a person to open a tab. An API sees only what the server sends — which covers SSR and prerendered Nuxt, the overwhelming majority of deployments — and it is the only option that runs unattended against a thousand domains. Use the API for the list, the console for the results that come back empty.
Pro tip: when a scan returns Vue.js but not Nuxt.js, do not assume the site is plain Vue. Check the HTML size first. A large server-rendered document with Vue markers and no Nuxt markers really is plain Vue, or Vue with a different meta-framework. A small shell means you learned nothing either way.
Related Reading
- How to Detect a Vue.js Website — The layer underneath Nuxt, and the generic markers that cannot tell the two apart
- Detect What JavaScript Framework a Website Uses — The full framework landscape when you do not yet know what you are looking at
- How to Detect if a Website Uses Next.js — The React-side counterpart, with the same meta-framework detection problem and a different set of markers
- How to Detect if a Website Uses React — The other half of the front-end split, from console checks to API automation
- How to Detect Vercel on Any Website — The PaaS behind nuxt.com, read from the server and x-vercel-id headers
- How to Detect Netlify Hosting on Any Website — The other common home for prerendered Nuxt builds
- Find Companies Using Node.js — The runtime every Nuxt detection implies, and what it is worth on its own
- Batch Scan 1,000 Websites for Tech Stack Data — Chunking, retries, and rate limits for lists past the 10-URL batch ceiling
- Detect Any Website’s Tech Stack With a Single API Call — Overview of the HTTP, DNS, and TLS detection layers
- Website Technology Checker API — Full endpoint reference and integration guide
Get Your API Key and Start Detecting
Nuxt detection comes down to one rule: read the HTML body, not the headers. The mount element, the /_nuxt/ asset path, and the __NUXT_DATA__ payload script are all written by the framework into the server response, and any one of them settles the question. The headers will tell you who hosts the site, which is a different and also useful answer.
Start with the free demo call, then move to a key when you want to run it against a list.
Try DetectZeStack Free
100 requests per month, no credit card required. HTTP + DNS + TLS detection included on every plan.
Get Your Free API Key