Anti-Bot

What Is Call Stack Depth Fingerprinting?

What Is Call Stack Depth Fingerprinting? — conceptual illustration
On this page

Stack depth fingerprinting measures the maximum JavaScript recursion depth a browser allows before throwing a RangeError: Maximum call stack size exceeded. The limit is determined by the engine (V8, SpiderMonkey, JavaScriptCore), the platform, the CPU architecture, and the stack frame size of the test function. Because the number is a property of the real engine and OS - not of the User-Agent - it is a low-cost way to tell which engine is actually running, and it betrays tools that claim one browser while running another underneath.

Quick facts

MeasuresMax recursion depth before RangeError (Maximum call stack size exceeded)
Varies byJS engine, OS, CPU architecture, and the test function frame size
RevealsThe real engine - V8 vs SpiderMonkey vs JavaScriptCore
CatchesFirefox-based tools (Camoufox) presenting a Chrome User-Agent
VariantMeasured separately on main thread, Workers, and WASM

How the limit is measured

The probe is a few lines: recurse a counter-incrementing function until it throws, and record the counter. The resulting number is surprisingly specific. V8 (Chrome), SpiderMonkey (Firefox), and JavaScriptCore (Safari) each allocate stacks differently and enforce different ceilings, so the depth lands in distinct ranges per engine. The exact value also shifts with CPU architecture (x86-64 vs ARM64), OS (stack size defaults differ), and the size of each frame - so probes fix the frame shape (number of arguments and locals) to keep the measurement comparable.

Because the number comes from the engine running real instructions, you cannot move it from JavaScript without changing how the engine actually executes - there is no property to overwrite.

Why it catches engine spoofing

The decisive use is catching tools whose engine does not match their claimed browser. Camoufox is Firefox under the hood; if it presents a Chrome User-Agent, its recursion depth lands in the SpiderMonkey range, not the V8 range - an immediate contradiction. The same applies to any "Chrome" that is really something else, or a JS runtime impersonating a browser. Measuring the depth separately on the main thread, in a Web Worker, and in WASM adds further resolution, because the ratios between those contexts are also engine-specific.

This is one of a family of engine-level probes (alongside Math precision and WASM tricks) that read the real implementation rather than the advertised one. The only robust defence is to actually run the engine you claim - a Chrome-based tool for a Chrome UA - or to patch the engine's stack limit at the C++ level to match the target, which is exactly the kind of deep change DIY stealth scripts cannot make.

Code example

javascript
// Measure max recursion depth (fix the frame shape for comparability)
function maxStackDepth() {
  let depth = 0;
  function recurse() { depth++; recurse(); }
  try { recurse(); } catch (e) { /* RangeError */ }
  return depth;
}

// Indicative ranges (vary by OS/arch/version - the engine clustering is the point):
//   V8 / Chrome           ~ 10k-15k
//   SpiderMonkey / Firefox~ different band
//   JavaScriptCore/Safari ~ different band
//
// A Chrome User-Agent whose depth lands in the SpiderMonkey band
// is a Firefox-based tool (e.g. Camoufox) wearing a Chrome UA.

Related terms

What Is Math & JS Engine Fingerprinting?
Math fingerprinting identifies a runtime by computing transcendental functions (sin, cos, tan, exp, log, pow) at fixed inputs and reading th…
What Is WASM Fingerprinting?
WebAssembly fingerprinting is a 2026 detection layer that probes the actual CPU through WASM SIMD instructions and uses WebAssembly.Memory({…
What Is Browser Fingerprinting?
Browser fingerprinting is a technique that identifies and tracks a visitor by combining dozens of small, observable characteristics of their…
What Is Fingerprint Lie Detection?
Fingerprint lie detection is the practice of verifying that the signals a browser reports are internally consistent and untampered, rather t…
What Is Camoufox?
Camoufox is a stealth-focused fork of Firefox with anti-fingerprinting patches applied at the C++ build level. Unlike playwright-stealth, wh…
Anti-Bot Vendor Detection Cheatsheet
The first step of any scrape against a protected site is identifying which anti-bot vendor is in front of it. The vendor determines almost e…
What Is Anti-Bot Detection?
Anti-bot detection is the set of techniques websites use to distinguish automated traffic from human users — and to block, challenge, or thr…
What Is Headless Browser Detection?
Headless browser detection is the set of probes anti-bot systems use to distinguish a headless or instrumented Chrome session from a real us…
What Is Browser Fingerprinting Evasion?
Browser fingerprinting evasion is the practice of configuring an automated browser so that the combined fingerprint it presents — canvas, We…
How Do Websites Detect Web Scrapers?
Websites detect scrapers by collecting hundreds of signals across the network, transport, browser, and behavioral layers, then scoring the c…

Concept map

How Stack Depth Fingerprinting connects

The terms most directly tied to this one. Hover a node to see its neighbours, click to preview, drag to rearrange.

0 terms · 0 connections
You are here · Anti-Bot
Building map…

Frequently asked questions

Why does maximum recursion depth differ between browsers?

Because it is set by the JavaScript engine and OS, not by the browser brand. V8, SpiderMonkey, and JavaScriptCore allocate stacks and enforce limits differently, and the value also shifts with CPU architecture and frame size. The depth therefore clusters by real engine, which is what makes it a fingerprint.

Can I spoof my stack depth from JavaScript?

No. The limit is a consequence of how the engine actually executes - there is no property to overwrite and no way to make recursion throw at a different point without changing the engine itself. That is exactly why it catches tools whose underlying engine differs from their claimed User-Agent.

How does stack depth catch Camoufox?

Camoufox is a Firefox fork, so its recursion depth falls in the SpiderMonkey range. If it presents a Chrome User-Agent, that depth contradicts V8's expected range, revealing a Firefox engine behind a Chrome identity. Measuring depth on the main thread, Workers, and WASM adds further engine-specific detail.

Last updated: 2026-05-30