NimbusX
00
› page loaded
← blog
mobile15.07.20267 min

Mobile fingerprints without a phone

An Android profile runs on an ordinary computer and receives a Trustworthy verdict from iphey. The expensive lesson was not to assign phone hardware by hand. One desktop-window constraint remains and is shown openly.

01How to enable it

Create a mobile profile with the flag:

$ python -m app.cli profile create \ --name mobile-01 --platform android

The engine selects a coherent mobile identity, including model, chipset, screen and memory. It reports the model in uaData.model, which is where detectors read it. The test suite scores 100 out of 100 and iphey returns Trustworthy; no physical phone is required.

02The model list we chose to remove

The first version assigned phone hardware from our own model list. That list paired a Pixel 7 with a Redmi chipset. One wrong chipset was enough for iphey to return Unreliable: detectors know real model-and-chipset combinations better than any list maintained by hand.

We removed the hand-built model list entirely. The engine now chooses the mobile identity, and a dedicated regression test prevents the old mistake from returning: NimbusX does not impose hardware on that identity. The lesson extends beyond mobile profiles. Internal coherence matters more than manual control over every value.

03Signals measured across profiles

Three mobile profiles created consecutively on a clean machine:

SurfaceResult
Windows-only fontsnone exposed; all thirteen checks passed
Video carddifferent in every profile
Reported screendifferent in every profile
Canvasdifferent in every profile
Logical processor counteight in every profile, as on the reference phones

Fonts are the clearest check. If a page saw Calibri or Segoe UI from a profile claiming to be a Pixel, the contradiction would be immediate: those fonts do not ship with Android. We tested thirteen fonts installed only with Windows or Microsoft Office, and the profile exposed none of them.

04The desktop-window limit

The mobile profile's layout viewport is wider than its reported screen. The engine changes screen and outerWidth, but the browser still runs in a real desktop window. The profile reports 360×800 while the layout viewport is 500×731. We tested the following approaches:

ApproachLayout viewport width
no adjustment500
412×915 window500
300×600 window500
render scale 1.27510
headless mode478

The constraint is Chrome's minimum desktop window width, roughly 500 CSS pixels. Phones do not use a viewport that wide, so the mismatch cannot be removed while the browser runs in a desktop window. Faking innerWidth independently of layout would not work. The first media query would reveal the real width and create two contradictory values instead of one.

What we could improve: after launch, NimbusX resizes the window to the height reported by the page, and CreepJS no longer highlights the Screen section. The remaining width mismatch is visible in the dashboard: the WIN cell is dimmed and the explanation appears below the table. Hiding it would serve no purpose because a website sees the mismatch before the user does.

05Read more

Consistency matters more than variety · How fingerprint checks connect profiles

Download NimbusXTechnical question: @Get_NimbusX_Bot