The Mosaic blog

News from the product, the engineering behind it, and the reasons we made the calls we made.

RSS feed

Headless is a way to be seen, beside a screenshot: a Mosaic leak test: every surface a site reads, checked from inside the profile page
Engineering

Headless is not a way to hide, it is a way to be seen

Headless Chrome names itself HeadlessChrome in its user agent and drops the real GPU. Why our background work runs headed, off-screen, instead.

Two routes to one value, and only one of them moved, beside a screenshot: mosaic settings showing the installed Tesseract Chrome engine and its version
Engineering

Half a spoof is a contradiction

Partial fingerprint spoofing detection is simple: ask one question two ways. We cut five spoofs that changed one route to a value and left the other.

1 sec: One command read a session cookie off the disk, beside a screenshot: importing a cookie jar into a Mosaic profile
Engineering

Chromium's mock keychain, and why we encrypt the store

Chromium's --use-mock-keychain keeps cookie encryption on but uses a password from its own source. We read a live session cookie off disk, then sealed it.

300: The page was told 300. The header still said 50
Engineering

The RTT client hint, read off the wire

ECT, RTT and Downlink headers behind a proxy, measured: a claimed round trip moved JavaScript to 300 and left the RTT header at 50. So we claim neither.

false: isTrusted: false, on every scroll it made, beside a screenshot: the Mosaic warm-up robot about to give a new profile a browsing history
Engineering

The warm-up robot that left a bot signature

Our warm-up robot scrolled with window.scrollBy, so pages saw isTrusted false and a scroll with no wheel. How a page detects that, and what we changed.

Values change in C++, not in the page, beside a screenshot: mosaic settings showing the installed Tesseract Chrome engine and its version
Engineering

Why we built our own Chromium instead of injecting JavaScript

Mosaic changes fingerprint values in C++ inside its own engine. Three measured differences between Chrome and plain Chromium explain why that matters.

The pasted line is the specification, beside a screenshot: a proxy provider in Mosaic: one gateway line that mints a separate session for every profile
Engineering

Reading a proxy seller's grammar off one pasted line

Proxy sellers put country, session and lifetime in the username. Mosaic reads the grammar off the line you paste and keeps every token it does not know.

5: Five products, told apart by their fields, beside a screenshot: filtering Mosaic profiles by tag: only the profiles tagged "shop" are listed
Engineering

Importing other browsers' libraries by shape, not file name

To migrate anti-detect browser profiles, Mosaic reads which product wrote the file from its fields, keeps what that product recorded and draws the rest.

Identical in two profiles and equal to this Mac
Engineering

The values every profile inherited from this Mac

A browser fingerprint value inherited from the host is identical across two unrelated profiles and equal to the computer. That test found dark mode and more.

A deleted profile has no browser left open, beside a screenshot: the Mosaic trash: deleted profiles kept for 30 days, restorable one by one
Engineering

Trashing a profile closes its browser, at every door

Delete a running profile in Mosaic and its browser closes first. If the browser will not close, the profile stays on the list, with its Stop button.

webdriver true versus webdriver false, each name in its own tile: true and trusted, false and flagged
Engineering

Why navigator.webdriver is true, and why false proves little

navigator.webdriver is true because automation set it on purpose. We measured a debug-attached Chrome reading true and still scoring 100 on IPHey.

An AI assistant that runs your browser profiles, beside a screenshot: the Mosaic MCP server: let an AI assistant manage profiles, proxies and launches
Engineering

Letting an AI assistant run browser profiles over MCP

Mosaic's MCP server lets Claude or any MCP client create, start and drive browser profiles. Three faults we found when a model was the caller.

0/100: A perfect score from a page that measured nothing
Engineering

fingerprint-scan.com bot score: 0 before anything was measured

fingerprint-scan.com shows Bot score 0/100 while its hash still reads collecting. Read the score only after the hash exists, and expect 15, not 0.

200: A homepage where the bot test used to be
Engineering

A retired bot test can still answer 200 and look like a pass

Antoine Vastel's fp-scanner demo now serves his homepage with HTTP 200, which a challenge reader scores as a pass. His tests moved; here is where.

Chrome versus Edge, each name in its own tile: One switch, two shapes, and Edge could not have both
Engineering

Why Mosaic profiles never claim Edge

Our Edge profiles sent either a full build in the User-Agent or an empty Sec-CH-UA-Bitness client hint. No real Edge sends either, so we refuse Edge.

15s: Fifteen seconds of input, then the score, beside a screenshot: the Mosaic warm-up robot about to give a new profile a browsing history
Engineering

Behaviour tests score your mouse, not just your browser

A behavioral bot detection test scores mouse paths and dwell next to browser attributes. Load one and touch nothing, and the score describes your stillness.

Two address families, one exit, beside a screenshot: a proxy check result in Mosaic: latency, exit address, ISP, HTTPS tunnelling and reputation
Engineering

An IPv4 and an IPv6 address from one proxy is one exit

A proxy that shows both an IPv4 and an IPv6 address is a dual-stack exit. Sites see either one, so look both up before you trust the location.

49: 49 detectors, five groups, one list
Engineering

49 browser fingerprint detectors, and how we read them

Our browser fingerprint detectors list: 49 public test pages in five groups, 40 read by a script and 9 kept as reference because they print no verdict.

Your dark mode, sent as a request header, beside a screenshot: mosaic general settings: theme and how profiles launch
Engineering

Your dark mode is sent as a request header

Sec-CH-Prefers-Color-Scheme sends your dark mode setting to any server that asks. On our profiles it carried this Mac's own settings, until each drew its own.

3: A resolver is a leak only next to your exit, beside a screenshot: a proxy check result in Mosaic: latency, exit address, ISP, HTTPS tunnelling and reputation
Engineering

A DNS server in another country is not always a leak

Our US exit resolved through Google in Germany, and nothing leaked. A foreign resolver in a DNS leak test matters only if it is your own ISP's.

Page versus Worker, each name in its own tile: One override, two answers from one browser
Engineering

setUserAgentOverride without metadata wipes your client hints

Without userAgentMetadata, setUserAgentOverride left our page with empty brands while a worker reported both. We set the User-Agent at launch instead.

Record: x86 versus Browser: arm, each name in its own tile: The record said x86 and the browser said arm
Engineering

Our profiles said x86 and the browser said arm

Chrome on an Apple silicon Mac sends Sec-CH-UA-Arch "arm". Our profile records said "x86", read by nothing, so we fixed the record, not the browser.

0: Candidates gathered with non-proxied UDP blocked, beside a screenshot: a Mosaic leak test: every surface a site reads, checked from inside the profile page
Engineering

Why video calls struggle in a proxied profile

WebRTC sends media over UDP, which an HTTP or SOCKS proxy in Chrome does not carry. With non-proxied UDP blocked, only a TURN relay over TCP is left.

5: Five BrowserLeaks rows we keep as reference
Engineering

BrowserLeaks gives you values, not verdicts

BrowserLeaks prints a canvas signature, a renderer and a JA3 hash, and no pass or fail. Each value means something only beside Chrome on the same machine.

SM-S918U: The model a phone sends when a site asks for it
Engineering

Sec-CH-UA-Model is empty on a desktop and a phone's name on Android

Chrome on Android freezes the model out of the User-Agent but still sends it in Sec-CH-UA-Model. Our first Android patch sent an empty one.

3: Three first-party sites, one tracker following you, beside a screenshot: a Mosaic leak test: every surface a site reads, checked from inside the profile page
Engineering

Why Cover Your Tracks sends you to firstpartysimulator.org

firstpartysimulator.org is an EFF domain. Cover Your Tracks loads it mid-test as a stand-in first-party site, so a hang there leaves the test running for ever.

504: Four 504s on one session, then a fresh one
Engineering

Four 504s on one session: rotate, don't retry

On a sticky residential proxy a session token is an exit, so retrying it asks a dead exit three more times. Rotate to a fresh session instead.

2^18.28: One in about 318,000, of the browsers it compared
Engineering

18.28 bits: what Cover Your Tracks' number measures

Bits of identifying information is log2 of how rare your browser is in the EFF's sample. 18.28 bits is about one in 318,000, and it is not a tracking score.

0: Candidates gathered, with the API still there, beside a screenshot: a Mosaic leak test: every surface a site reads, checked from inside the profile page
Engineering

A browser with no RTCPeerConnection doesn't exist

Deleting WebRTC leaves a Chrome no one runs. Zero candidates with the API still present is every machine on a UDP-blocked network, so that is what we ship.

The first launch of a session wore a different identity
Engineering

A fingerprint that depended on launch order

Chrome's --user-agent flag left Sec-CH-UA-Bitness empty, and a cache empty at every app start decided when we sent it. One profile wore two identities.

1 of 3: Three flags on the command line, one in the binary
Engineering

Two WebRTC flags we used never existed in Chromium

Chrome has one WebRTC command line flag for leaks: --webrtc-ip-handling-policy. We also sent two that don't exist, and Chromium accepted both in silence.

1 of 49: One row of 49 that would not load, beside a screenshot: the Mosaic sidebar with profiles running, each with its own window
Engineering

fingerprint.com wouldn't load through our proxy, and that was a result

Through one residential exit the FingerprintJS demo hung; from the same Mac with no proxy it loaded. Our runner blamed itself. The exit was why.

153 versus 153.0.8010.37, each name in its own tile: A version no Chrome has ever reported
Engineering

A full Chrome version with no build number is one no Chrome shipped

Our engine reported uaFullVersion as "153". Real Chrome always sends four numbers. Sending the full build moved FingerprintJS's confidence to stock's 0.99.

243: White dropped to 243 and only the screen showed it, beside a screenshot: mosaic general settings: theme and how profiles launch
Engineering

A canvas readback is not a rendering check

Forcing Chrome's colour profile to hdr10 lifted a page's dark background and dimmed its white on macOS. Four checks missed it; a screen capture did not.

One sample of the pool, not the exit, beside a screenshot: a proxy check result in Mosaic: latency, exit address, ISP, HTTPS tunnelling and reputation
Engineering

Scoring a rotating proxy scores one draw from the pool

A reputation check on a rotating proxy scores whichever exit the pool handed out that second. Pin a sticky session to score the address you will browse from.

The .local address is Chrome working, beside a screenshot: a Mosaic leak test: every surface a site reads, checked from inside the profile page
Engineering

The .local address in your WebRTC test is Chrome working

A random .local name in a WebRTC leak test is Chrome hiding your LAN address. We once switched it off, and the empty result was the louder tell.

Launch 1 versus Launch 2, each name in its own tile: Different per profile, the same every launch
Engineering

A FingerprintJS pass has two halves

A FingerprintJS visitor ID should differ per profile and hold across launches of one. Colliding ids link profiles; ids that change flag a spoofer.

A check that lies is worse than one that is missing
Engineering

Why our reputation check doesn't ask Spamhaus

Spamhaus refuses queries that arrive through public resolvers, so asking it from an ordinary computer returns a confident wrong answer. We left it out instead.

90 s: One 90-second run would have saved four days, beside a screenshot: a Mosaic leak test: every surface a site reads, checked from inside the profile page
Engineering

The control that settles "is it our patches?"

Unpatched Chrome for Testing got the same IPHey verdict as our engine, so our patches were not the cause. Its voice list still differs from Chrome's.

Asked for a name, never for an address, beside a screenshot: routing Mosaic launches through Proxyman, Charles or mitmproxy to read their traffic
Engineering

A CONNECT to a raw IP means your machine resolved the name

To check if DNS goes through your proxy, read what the proxy is asked for. CONNECT example.com:443 means it resolved the name; a raw IP means you did.

1/20 px: Up to a twentieth of a pixel per glyph
Engineering

Same fonts, different measurements: per-profile glyph advances

Font fingerprint randomization can hide fonts or change how wide glyphs measure. Hiding read as masking; per-profile glyph advances did not.

Exit versus Resolver, each name in its own tile: A resolver is a leak only next to an exit
Engineering

Is a Google DNS server in your leak test a leak?

Google DNS in a leak test is not a leak by itself. It depends on where you browse from: the resolver your own ISP runs is the leak, someone else's is not.

3 in 20: Stock Chrome, masked 3 times in 20, beside a screenshot: a profile fingerprint in Mosaic: GPU, screen, fonts, timezone and language matched to the exit
Engineering

Pixelscan calls a stock Chrome masked 3 times in 20

A Pixelscan false positive, measured: an untouched Google Chrome read 'Masking detected' on 3 of 20 runs. Our fresh profiles read it once in 74.

400: One dead exit is not a dead proxy, beside a screenshot: a proxy check result in Mosaic: latency, exit address, ISP, HTTPS tunnelling and reputation
Engineering

"400 Target website error" and one observation of a pool

A proxy's 400 Target website error usually means the pool gave you an exit that could not reach the site. One answer like that does not make the proxy dead.

MAP: The name that has to survive goes first
Engineering

--host-resolver-rules: the first match wins

Chrome's --host-resolver-rules tries MAP rules in order and stops at the first match. EXCLUDE is not ordered. A wildcard put first ate our extension's API call.

Runtime.enable flips a detector, beside a screenshot: a Mosaic leak test: every surface a site reads, checked from inside the profile page
Engineering

Runtime.enable flips a detector, so we don't call it

Runtime.enable detection, measured: one DevTools command turned a clean Mosaic profile into isBot=true on deviceandbrowserinfo. We removed all five calls.

User-Agent versus ClientHello, each name in its own tile: The handshake has to agree with the header
Engineering

Why we leave the TLS and HTTP/2 fingerprints alone

A TLS fingerprint mismatch is a User-Agent claiming a browser the handshake did not come from. We avoid it by never claiming a Chrome the engine is not.

Two latency figures that belong to the computer
Engineering

baseLatency is shared by every profile and moves with your headphones

AudioContext baseLatency and outputLatency come from the real output device, so every browser profile on one computer reports the same pair.

12!: Twelve extensions have 479,001,600 orders, beside a screenshot: routing Mosaic launches through Proxyman, Charles or mitmproxy to read their traffic
Engineering

Chrome shuffles its ClientHello, so compare sets

Chrome TLS extension permutation reorders the ClientHello on every connection. Only the extension order moves, so a client that repeats its order is not Chrome.

30%: Drawn from what browsers send, not what people say, beside a screenshot: mosaic general settings: theme and how profiles launch
Engineering

Why 30% of our profiles use dark mode

The prefers-color-scheme dark mode share in real traffic is far below survey figures. Every profile on our Mac said dark; now each draws dark 30% of the time.

NOTFOUND: Every local lookup fails, so none of them leak
Engineering

DNS prefetching, the lookup that skips your proxy

Chrome's DNS prefetcher resolves names through your own resolver even with a proxy set. Mapping every name to NOTFOUND makes the leak fail closed.

20: Compared unsorted, twenty names were out of place, beside a screenshot: mosaic settings showing the installed Tesseract Chrome engine and its version
Engineering

Sorting the property list hid the question

Property enumeration order is a fingerprint that sorted diffs can't see. Compared unsorted, our engine differed from Chrome only in its 20 field-trial entries.

Exit, tunnel and stability are three answers, beside a screenshot: a proxy check result in Mosaic: latency, exit address, ISP, HTTPS tunnelling and reputation
Engineering

A green tick that means the socket opened is worthless

A proxy checker can pass while sites fail, because most test plain HTTP and the browser needs a CONNECT tunnel. Exit and stability are separate answers too.

CONNECT: Answers HTTP, refuses the tunnel
Engineering

A proxy that answers HTTP and refuses CONNECT

A proxy that works for HTTP but not HTTPS is refusing CONNECT, the tunnel every HTTPS page needs. A check that fetches a plain-HTTP page cannot see it.

90: Both scored 90. Only one was about the browser., beside a screenshot: a Mosaic leak test: every surface a site reads, checked from inside the profile page
Engineering

Same IPHey score, opposite reasons

IPHey Unreliable on a normal Chrome is usually the exit. Our profile and a stock Chrome both got MX 90, for a browser signal and a location signal.

344: One value, the same on every profile we had made
Engineering

344 profiles said "denied": one value, everywhere

Notification permission became a fingerprint: Notification.permission read denied on all 344 of our profiles, where an unconfigured Chrome says default.

Link opened versus IP changed, each name in its own tile: Opening the link is not proof the IP changed
Engineering

"Rotation URL opened" is not "the IP changed"

Mobile proxy change-IP link not working? It worked if it answered 2xx and the exit differs once the modem redials. Our own Proxies page checked neither.

socks5h: socks5 and socks5h: where Chrome resolves the name
Engineering

socks5 and socks5h: where Chrome resolves the name

In curl, socks5h sends the hostname to the proxy and socks5 resolves it locally. Chrome's socks5 already sends the name; the leak is elsewhere.

6: Six profiles, one machine, six countries, beside a screenshot: a Mosaic leak test: every surface a site reads, checked from inside the profile page
Engineering

A profile in Austria claimed New York

Browser location does not match IP: a no-proxy profile made in Austria claimed New York. One failed lookup was never retried, and a table filled the gap.

Read it twice: v·f, then v·f·f, beside a screenshot: a Mosaic leak test: every surface a site reads, checked from inside the profile page
Engineering

An audio spoof that changed the sound every time it was read

getChannelData returns the buffer's own memory, so our audio noise multiplied samples on every read: v·f, then v·f². A seeded byte fixed it.

1 card: Same exit, same minute: the location card went our way, beside a screenshot: the Mosaic sidebar with profiles running, each with its own window
Engineering

Why IPHey's location card can be greener on a profile than on Chrome

On one US exit in one minute, stock Chrome got IPHey's masked or inconsistent location data and our profile got green. The difference was the timezone.

1 of 5: The first call answered, the next four timed out
Engineering

A spoof that answers once: the geolocation bug we shipped

A geolocation spoofing timeout we shipped: the first getCurrentPosition got the exit's coordinates, every later call failed with code 3. One latch was to blame.

Five cards, one number: read the red one, beside a screenshot: a profile fingerprint in Mosaic: GPU, screen, fonts, timezone and language matched to the exit
Engineering

IPHey's score moves on unmodified Chrome. Read the card.

A low IPHey MX score is the sum of five cards. Untouched Chrome scored 100, 100, 70 and 0 in one afternoon, so the red card tells you more than the number.

3: Our relay's CONNECT differed from Chrome's three ways
Engineering

Our proxy relay told the gateway it was a script

Chrome sends Proxy-Connection: keep-alive, lower case, to every proxy. Our relay sent Keep-Alive, no User-Agent and Connection: close, until we copied Chrome.

f5337a44: One scene, one Mac, one hash for every profile
Engineering

Every profile on one Mac drew the same WebGL image

A WebGL fingerprint is the same in every browser profile on one machine because the GPU draws it. Ours was too, until per-profile noise moved the hash.

49: 49 detectors, read by a script, with nobody watching
Engineering

Running 49 fingerprint tests unattended, and what that takes

To automate browser fingerprint testing, tell a failed profile from a dead site, an unreadable page and your own bug. Our runner names each across 49 rows.

The relay carries ciphertext, so the order arrives intact
Engineering

Header order is a fingerprint, and a tunnel cannot touch it

Sites read the order of Chrome's HTTP headers as well as their values. Through a CONNECT tunnel a relay carries ciphertext, so it cannot reorder a thing.

20: Twenty APIs a page could find on us and not on Chrome, beside a screenshot: mosaic settings showing the installed Tesseract Chrome engine and its version
Engineering

Twenty APIs Chrome doesn't have: Chromium's field trials

Unbranded Chromium runs its field-trial testing config at every launch. Against Chrome 153 that was 20 API differences, and one switch moved them all.

After launch versus Before launch, each name in its own tile: Counted after the start, and before it
Engineering

Chrome opens connections before your test starts

We counted 1, 0 and 0 CONNECTs in three launches and thought Chrome was bypassing the proxy for HTTPS. Our counter was reset after Chrome had started.

Direct: h3 versus Proxied: h2, each name in its own tile: One site, two routes, two protocols
Engineering

What happens to QUIC when Chrome has a proxy

With an HTTP, HTTPS or SOCKS5 proxy set, Chrome reaches sites over TCP tunnels, so a page that gets HTTP/3 direct gets HTTP/2 through the proxy.

33: 33 patched functions gave their source to an iframe
Engineering

Why we change fingerprints in C++, not JavaScript

A JavaScript spoof is one realm deep. An iframe read the real source of 33 of our patched functions; the same values changed in C++ agree everywhere.

41 of 45: Hand-typed renderer strings, wrong in one field
Engineering

41 of 45 hand-written Windows renderer strings were wrong

Chrome's ANGLE Direct3D11 renderer string carries the GPU's PCI device id. Our hand-typed Windows rows left it out, a string no real driver produces.

v4 + v6: Two addresses, one exit, three wrong verdicts
Engineering

IPv4 from one probe, IPv6 from the other: one exit, not two

A proxy that shows an IPv4 address on one checker and an IPv6 address on another is usually one dual-stack exit. Rotation only shows within one family.

-130: Chrome never reached the proxy at all, beside a screenshot: routing Mosaic launches through Proxyman, Charles or mitmproxy to read their traffic
Engineering

ERR_PROXY_CONNECTION_FAILED is about the first hop

Chrome's proxy connection failed error means it never reached the proxy address it was given. Check the host, the port and anything local before the exit.

4 = 1: Four profiles, one session id, one address
Engineering

Same proxy session on multiple profiles: forty profiles, forty exits

The same proxy session on multiple profiles means one exit IP for all of them. A batch of ours did it in September 2026; now every profile mints its own.

Sixty honest fields and one string, beside a screenshot: a profile fingerprint in Mosaic: GPU, screen, fonts, timezone and language matched to the exit
Engineering

Pixelscan reads sixty WebGL fields, and the renderer string is one

Pixelscan's WebGL fingerprint is a render hash plus about sixty driver fields beside the renderer string. A chip that never existed failed like a real one.

0108: The renderer is one string beside sixty answers, beside a screenshot: mosaic settings showing the installed Tesseract Chrome engine and its version
Engineering

A WebGL renderer string is a claim and the limits are the evidence

WebGL MAX parameters, shader precision formats and the extension list come from the real driver. Our engine moves them only with data from a real device.

Ordered list versus Sorted set, each name in its own tile: Two handshakes, compared field by field
Engineering

Comparing two TLS handshakes: compare the set, not the order

To compare two TLS fingerprints, label GREASE and compare the extension set sorted. Our first diff against Chrome showed two differences, both noise.

-111: The proxy said no, and Chrome threw away the reason
Engineering

What ERR_TUNNEL_CONNECTION_FAILED is telling you

Chrome's tunnel connection failed error means the proxy refused the CONNECT tunnel. In our runs the usual cause was a sticky session the gateway had retired.

90s: Three Windows claims, three scans that never ended
Engineering

When Pixelscan never stops scanning

Pixelscan stuck on scanning for 90 seconds was, in our runs, a profile claiming Windows on a Mac. A scan that never returns is a non-verdict, not a slow pass.

null, and error 1280, until the page asks, beside a screenshot: a profile fingerprint in Mosaic: GPU, screen, fonts, timezone and language matched to the exit
Engineering

UNMASKED_RENDERER is null until a page asks for it

Chrome returns null for the unmasked WebGL renderer until the page calls getExtension, so a spoof that answers it earlier is a two-line tell.

1704: The first licence message: 1704 bytes where Chrome sends 2
Engineering

Widevine device certificate privacy: one key for every profile

Widevine device certificate privacy needs a Google-signed browser. Without it, the first licence message is 1704 bytes where Chrome sends 2.

199: Nineteen voices only Google's own build ships, beside a screenshot: mosaic settings showing the installed Tesseract Chrome engine and its version
Engineering

199 voices: how a speech list tells Chromium from Chrome

speechSynthesis.getVoices() lists 199 voices in Google Chrome on our Mac and 180 in any unbranded Chromium. A page reads the difference in one call.

The CreepJS proxy test is not about your proxy
Engineering

The CreepJS proxy test is not about your proxy

CreepJS's proxy page looks for JavaScript Proxy objects wrapped around native functions. A flag there names a spoofing script, not your IP address.

Reading a ClientHello with a one-minute listener, beside a screenshot: routing Mosaic launches through Proxyman, Charles or mitmproxy to read their traffic
Engineering

Reading a browser's ClientHello with a one-minute listener

A raw TCP listener that reads the first TLS record and hangs up captures a browser's ClientHello. Ours and branded Chrome's matched in every field.

4096: Two ways to read one WebGL image, beside a screenshot: mosaic settings showing the installed Tesseract Chrome engine and its version
Engineering

readPixels and toDataURL read a canvas from opposite ends

readPixels starts at the bottom row and toDataURL at the top, so position-keyed WebGL noise disagreed with itself. Keyed on colour, 4096 of 4096 pixels agree.

A lie is a function that does not look native
Engineering

What CreepJS's prototype page tells you about JavaScript spoofing

CreepJS's prototype page checks each native function's keys, source and errors. A value patched in JavaScript trips it; a value changed in C++ leaves nothing.

17 / 18: Chrome 152 and 153, one extension apart, beside a screenshot: the Mosaic sidebar with profiles running, each with its own window
Engineering

JA4 moves with the Chrome major, and that is not a tell

Chrome 152 read t13d1517h2 and 153 read t13d1518h2: one TLS extension apart. Compare a JA4 only against a Chrome of the same major version.

18: 18 TLS extensions, the same as Google's own build, beside a screenshot: mosaic settings showing the installed Tesseract Chrome engine and its version
Engineering

Why our engine has no TLS fingerprint setting

You can't change Chrome's TLS fingerprint from a setting, and we chose not to patch it: our engine's JA4 matched Google's own build byte for byte.

Port 11000 is SOCKS5. The line never says so., beside a screenshot: bulk-importing proxies into Mosaic: every line read, new and duplicate ones told apart
Engineering

The port number told us whether a proxy was SOCKS5

Nothing in host:port:user:pass says HTTP or SOCKS5, and curl assumes HTTP. At CatProxies we asked the port: 11000 answered SOCKS5, 10000 HTTP.

76: Same drawing, two places, 76 bytes apart, beside a screenshot: a Mosaic leak test: every surface a site reads, checked from inside the profile page
Engineering

The four-line probe that catches position-keyed canvas noise

To detect canvas noise injection, draw one shape twice at two offsets and diff them. A real browser gives 0 bytes; our old noise gave 76.

0 lies: A CreepJS lie, and why stock Chrome has none
Engineering

What a CreepJS lie is, and why stock Chrome has none

CreepJS lies detected means an API behaved unlike the native one: wrong toString, wrong descriptor, or a worker that disagrees. Stock Chrome has none.

Two JA3 hashes, one JA4, beside a screenshot: routing Mosaic launches through Proxyman, Charles or mitmproxy to read their traffic
Engineering

Why Chrome's JA3 hash changes on every connection

Chrome's JA3 changes because Chrome shuffles its TLS extension order on every connection, and JA3 hashes that order. JA4 sorts first and holds still.

Every account its own browser. One price for all of them.

Free holds 3 profiles and 10 profile creations, with no card. Pro is $49 a month for any number, or $490 a year with 2 months free. Try it for 14 days; cancel before day 14 and you pay nothing.