Detect Nuxt JS Website: 5 Signals and a Free API Call

September 19, 2026 · 10 min read

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.

CategoryWhy Nuxt is filed here
JavaScript frameworksThe Vue-based component layer
Web frameworksRouting, data fetching, middleware
Web serversThe Nitro server that handles SSR requests
Static site generatorPrerender 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:

SiteServer headerX-Powered-By
nuxt.comVercelabsent
ui.nuxt.comVercelabsent
about.gitlab.comcloudflareabsent

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:

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 Key

Where 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

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

Get API updates and tech detection tips

Join the mailing list. No spam, unsubscribe anytime.