Fix deviceMemory & hardwareConcurrency Mismatch (2026)
The profile looked clean. Canvas fingerprint — unique, consistent, no lies detected. WebGL renderer string matched a real Intel UHD 620. Timezone aligned with the proxy. Everything CreepJS checks? Green.
Then Cloudflare blocked it anyway.
I spent three hours debugging this last month before I found the issue. The profile claimed navigator.hardwareConcurrency = 16 — a beefy 16-core machine. But the actual laptop running JustBrowser? An M1 MacBook Air with 8 cores. When Cloudflare's detection script ran a parallel Web Worker benchmark, the timing screamed "this browser is lying about its core count."
Sixteen declared cores. Eight actual. Benchmark runs in half the expected parallelism. That's not a fingerprint mismatch — that's a coherence failure. And coherence failures get you blocked.
This is the detection vector that trips up operators who've mastered the obvious stuff. Canvas spoofing? Handled. WebGL? Handled. Timezone-proxy alignment? Handled. But the declared hardware specs? People set them to random "realistic" values and never think about whether the browser can actually perform like those specs.
I've screwed this up myself more times than I'd like to admit.
By the end of this guide, you'll understand how deviceMemory and hardwareConcurrency get cross-validated against actual performance — and how to configure profiles where the declared specs match measurable behavior.
Prerequisites
- JustBrowser installed (the 7-day trial is full access, which is all this needs)
- Basic understanding of browser fingerprinting
- 15 minutes
- A profile you want to audit
If you're new to fingerprint testing, the CreepJS walkthrough covers the fundamentals. What we're covering here goes deeper into a specific coherence check that CreepJS doesn't always surface clearly.
What Scripts Actually Check
Let me show you what a detection script sees.
Open your browser console and run:
console.log('Declared RAM:', navigator.deviceMemory, 'GB');
console.log('Declared cores:', navigator.hardwareConcurrency);
On my M1 MacBook Air, I get:
Declared RAM: 8 GB
Declared cores: 8
Simple enough. But here's what a detection script does next:
// Parallel benchmark - time how fast we can run workers
const workerCount = navigator.hardwareConcurrency;
const workers = [];
const start = performance.now();
for (let i = 0; i < workerCount; i++) {
workers.push(new Promise(resolve => {
const blob = new Blob([`
let sum = 0;
for (let i = 0; i < 10000000; i++) sum += Math.sqrt(i);
postMessage(sum);
`], {type: 'application/javascript'});
const worker = new Worker(URL.createObjectURL(blob));
worker.onmessage = () => { worker.terminate(); resolve(); };
}));
}
Promise.all(workers).then(() => {
console.log('Parallel time:', performance.now() - start, 'ms');
});
A 16-core machine running 16 workers in true parallel finishes in roughly 1/16th the time of serial execution. An 8-core machine claiming 16 cores? The workers queue up. The timing exposes the lie.
Detection scripts don't need to be this obvious about it. They embed these benchmarks in canvas rendering, audio processing, or crypto operations. The point is: they measure whether your browser performs like its declared specs suggest.
Frankly, it's a bit paranoid. But platforms got burned by bots hard enough that paranoid became baseline.
The deviceMemory Problem
navigator.deviceMemory is worse. It returns an approximation of RAM: 0.25, 0.5, 1, 2, 4, or 8 GB. That's the full range — just six possible values. Seems easy to spoof, right?
Here's the catch. Detection scripts can't directly measure your RAM, but they can observe memory allocation behavior:
- Allocation speed: Large typed array creation is faster on machines with more RAM (less pressure to garbage collect)
- GC timing: Low-memory machines trigger garbage collection more frequently
- Buffer limits: Browsers enforce different limits on ArrayBuffer sizes based on available memory
A profile claiming 8GB that triggers aggressive GC after 50MB of allocations isn't fooling anyone. The browser's behavior contradicts its declaration.
I'll be honest — deviceMemory timing attacks are harder to pull off than hardwareConcurrency ones. They require sustained memory pressure and careful measurement. Most fraud teams probably don't bother. But the ones at Stripe, PayPal, the top ad networks? They use these signals. If you're hitting walls on platforms with serious fraud detection — payment processors, high-value ad networks — this matters.
(I personally think the memory-based detection is overkill, but here we are.)
How Antidetect Browsers Get This Wrong
Most antidetect browsers let you set deviceMemory and hardwareConcurrency to any value. Great for uniqueness. Terrible for coherence.
I've seen three failure modes:
1. Random high values
People set 32GB RAM and 24 cores because "looks like a developer machine." Their actual laptop has 8GB and 4 cores. Every benchmark screams fake. This is the most common mistake I see in Discord support channels — someone wants their profile to look impressive instead of consistent. Vanity fingerprinting, basically.
2. Mismatched within profile
DeviceMemory set to 4GB but hardwareConcurrency to 16. That's a weird machine. 16-core systems don't ship with 4GB RAM. Detection scripts flag statistically unlikely hardware combinations. It's like claiming you drive a Lamborghini with a lawnmower engine.
3. Values don't match the fingerprint persona
A profile configured to look like Windows 10 on an Intel i3 reporting 16 cores and 32GB RAM. i3 processors don't have 16 cores. Ever. The user agent says one thing, the hardware specs say another. Coherence failure.
Step 1: Audit Your Current Profile
Launch your JustBrowser profile and run a full coherence check.
Open the console and test the declared values:
// Declared specs
console.log('deviceMemory:', navigator.deviceMemory);
console.log('hardwareConcurrency:', navigator.hardwareConcurrency);
Now run a quick parallel benchmark:
// Time a parallel workload
async function benchParallel(threadCount) {
const workers = [];
const start = performance.now();
for (let i = 0; i < threadCount; i++) {
workers.push(new Promise(resolve => {
const code = `
let x = 0;
for (let j = 0; j < 5000000; j++) x += Math.sin(j);
postMessage(x);
`;
const w = new Worker(URL.createObjectURL(new Blob([code])));
w.onmessage = () => { w.terminate(); resolve(); };
}));
}
await Promise.all(workers);
return performance.now() - start;
}
// Run with declared count vs actual system performance
const declared = navigator.hardwareConcurrency;
const time = await benchParallel(declared);
console.log(`${declared} workers completed in ${time.toFixed(0)}ms`);
Compare this across profiles. A profile claiming 16 cores should complete this benchmark approximately twice as fast as a profile claiming 8 cores on the same physical machine.
If the timing is nearly identical regardless of declared core count? Your hardwareConcurrency is lying and the timing proves it.
Step 2: Configure Coherent Hardware Specs in JustBrowser
In JustBrowser, open your profile's fingerprint settings.
For hardwareConcurrency:
- Navigate to Hardware Identity
- Find "CPU Cores (hardwareConcurrency)"
- Set this to match your actual physical hardware — or lower
The key insight: you can claim fewer cores than you have, but not more. A 16-core machine can convincingly claim to be 4-core (just don't use all cores). A 4-core machine cannot convincingly claim 16 — the parallel execution timing exposes it.
For multi-account operations, I typically set hardwareConcurrency to 4 or 8 across all profiles regardless of actual hardware. These are common values that blend into fingerprint populations, and most machines have at least 4 cores. The profiles look different from each other in other parameters, but the core count stays consistent and verifiable.
For deviceMemory:
- Find "Device Memory (GB)"
- Set this to match or understate your actual RAM
Same principle. 32GB actual can claim 8GB. 4GB actual claiming 32GB will fail memory allocation benchmarks. No way around physics.
JustBrowser's native Chromium engine handles this better than extension-based antidetect tools because it spoofs hardwareConcurrency, deviceMemory and the cpuPerformance tier at the C++ level, so every context (workers and iframes included) reports the same values. The override is engine-level rather than a JavaScript getter patch — but it does not throttle real execution, which is why you should declare at or below your real hardware so the timing checks still agree.
Step 3: Match Hardware to Your Fingerprint Persona
Here's where coherence gets interesting. Your hardware specs need to make sense with the rest of your fingerprint.
If your profile claims:
- Windows 10 Home
- Intel Core i5-8250U processor (from User Agent or hints)
- 1920x1080 screen
Then deviceMemory and hardwareConcurrency should match what that laptop actually has:
- i5-8250U has 4 cores / 8 threads → hardwareConcurrency: 8
- Typical laptops with this CPU ship with 8-16GB → deviceMemory: 8
A profile claiming i5-8250U with 24 cores? Impossible. Detection scripts know this.
JustBrowser's fingerprint generator creates coherent hardware profiles by default. It picks CPU specs, memory, and core counts that actually ship together. If you're manually overriding — stop. Let the generator create coherent combinations, then only tweak parameters that don't affect this coherence (canvas noise, font ordering, etc.).
Step 4: Test Against Real Detection
Run your configured profile against detection tools that check timing coherence.
CreepJS: Visit the test page and expand the "Hardware" section. It shows deviceMemory and hardwareConcurrency. More importantly, look at the trust score — timing inconsistencies lower it.
BrowserLeaks: Their Navigator section shows the declared values. Their WebGL section shows GPU capabilities. Cross-check: do the CPU specs match the GPU specs? A $300 laptop GPU with a server-class CPU is suspicious.
Pixelscan: Reports hardware specs and flags inconsistencies. Pixelscan is particularly aggressive about hardware coherence — it'll fail profiles that pass other tests. Annoying but useful for catching issues early.
For automation-heavy workflows using Playwright or Puppeteer, you can script these checks. Spin up a profile, run a benchmark, log the timing, compare against expected values. Automate the sanity check.
Common Errors and How to Fix Them
Benchmark timing doesn't scale with declared cores
Cause: You're claiming more cores than your actual machine has. Worker parallelism is bottlenecked by real hardware.
Fix: Lower hardwareConcurrency to your actual core count or below. Never claim more cores than you have.
Profile claims 8GB but triggers GC at 100MB
Cause: Your actual machine has 4GB or less. The browser's memory management exposes the real constraint.
Fix: Set deviceMemory to 4 or lower. Match your actual RAM.
Detection fails despite correct values
Cause: The values are correct but don't match other fingerprint elements. CPU/GPU/RAM combination is impossible.
Fix: Use JustBrowser's coherent fingerprint generator instead of manual overrides. Let it pick combinations that actually exist in the wild.
Tests pass but still getting blocked on specific platforms
Cause: That platform runs proprietary timing benchmarks you can't easily test for.
Fix: Try values closer to your actual hardware. The closer to reality, the harder to detect. If you're on an 8-core machine, claim 8 cores — don't get clever with 6 or 12. I learned this the hard way after wasting a week trying to outsmart detection systems that, surprise, were smarter than me.
Why This Coherence Check Exists
Five years ago, nobody ran timing benchmarks. Scripts just read navigator values and trusted them.
Then antidetect browsers became mainstream. Everyone started spoofing deviceMemory and hardwareConcurrency. Detection adapted.
The arms race works like this: spoofing gets easy, detection gets harder. Today's sophisticated detection doesn't trust declared values — it verifies them. Canvas fingerprinting went through the same evolution. WebGL went through it. Now hardware specs are getting the same treatment.
Platforms like Amazon, Facebook, and Google have internal fraud teams that know exactly how antidetect browsers work. Their analytics systems track user behavior patterns alongside fingerprinting. They read the same blogs we do. They buy the same tools to understand what they're detecting. When I see a new detection technique in a research paper, I assume it's already deployed at scale. The timing-coherence checks I'm describing aren't theoretical — they're active.
(And honestly? Kind of impressive engineering. Frustrating when you're on the antidetect side, but I can respect it.)
Next Steps
Hardware coherence is one piece of the fingerprint puzzle. Once your profiles pass this check:
-
Test timezone alignment — A profile claiming to be in Germany should have Europe/Berlin timezone. Our timezone-proxy mismatch guide covers this.
-
Verify WebGL coherence — The GPU renderer string should match the CPU class. The WebGL fingerprinting deep-dive explains what to check.
-
Run full fingerprint tests — CreepJS, FingerprintJS Pro, BrowserLeaks, Pixelscan. All of them. A profile that passes all four is genuinely clean.
If you're running email outreach alongside multi-account operations, consistent infrastructure matters there too — warmup domains, sending patterns, reply behavior. Different domain, same principle: systems detect inconsistency.
And if you're monitoring ad traffic for click fraud, the fingerprint detection techniques we're evading are the same ones fraud detection uses. It's useful to understand both sides.
The profile that got Cloudflare blocked? Fixed it by setting hardwareConcurrency to 8 (matching the actual M1) instead of 16 (a number I picked because it "looked powerful"). Passed the next day. Same fingerprint. Same canvas. Same WebGL. Just coherent hardware specs.
Turns out looking powerful is less important than looking real. Who knew.
Frequently Asked Questions
Why do detection scripts cross-check deviceMemory and hardwareConcurrency against actual performance?
Because these values are trivial to spoof — any antidetect browser can override navigator.deviceMemory and navigator.hardwareConcurrency with whatever numbers you want. Detection scripts got smart. They run micro-benchmarks that stress the CPU or allocate memory, then compare measured performance against declared specs. A profile claiming 32GB RAM and 16 cores that runs a matrix multiplication like a 4GB/4-core laptop is lying. The timing can't lie.
What's the difference between deviceMemory and hardwareConcurrency fingerprinting?
navigator.deviceMemory reports approximate RAM in gigabytes (values like 0.25, 0.5, 1, 2, 4, 8). navigator.hardwareConcurrency reports logical CPU cores. Both are used for fingerprinting because they're fairly stable per device but vary across devices. The difference: memory affects allocation benchmarks while cores affect parallel workload timing. Sophisticated detection checks both against actual measured performance.
Can I just set deviceMemory and hardwareConcurrency to common values to blend in?
Partly. Setting common values (8GB RAM, 8 cores) makes you less unique in the fingerprint database. But if your actual machine has 4GB and 2 cores, benchmark timing will expose the lie. The solution isn't just picking plausible values — it's matching what you declare to hardware that can back it up. JustBrowser spoofs both values (plus the cpuPerformance tier) at the C++ level; pair that with declared values at or below your real hardware so benchmarks agree.
Do all fingerprinting services check timing coherence?
Not all. Basic fingerprinting (older scripts, simple canvas-only checks) just reads the declared values. Advanced detection like CreepJS, FingerprintJS Pro, and custom enterprise systems run timing benchmarks. The trend is toward more timing checks, not fewer. If you're passing simple tests but still getting flagged on sophisticated platforms, timing coherence is often the gap.
Try JustBrowser
Native Chromium antidetect browser — not extension-based. Real C++ engine patches at the canvas / WebGL / audio / font / screen layer, so 40+ identity parameters are genuine, not faked. REST API for Playwright, Puppeteer, Selenium. $9.99/month or $99.99/year. 7-day free trial, card required — cancel any time in the seven days and you are not charged. Unlimited profiles.
Get started → · How it differs from Multilogin / GoLogin / AdsPower
Related Posts
Ready to manage multiple accounts?
Seven days free, then $9.99/month — one plan, everything included.