mirror of
https://github.com/feder-cr/invisible_playwright.git
synced 2026-06-19 09:08:06 +02:00
- BINARY_VERSION -> firefox-12 (self-calibrating font widths, per-family canvas distinctness, render-noise that preserves solid reference renders). - font_pool: the standard Windows fonts (Calibri, Franklin Gothic, Gadugi, Javanese Text, Myanmar Text) move from the per-profile optional set to core, so they are always present and the detected font set matches a real Windows install on every host. Defensive dedup in derive_font_prefs. - GPU persona applied on every platform (Linux/macOS present a coherent Windows GPU + WebGL params); pool re-rooted on a real-device GPU mix; render seeds recalibrated. - prefs: emit absolute per-family font widths that the binary self-calibrates. - geoip: always pull the latest mmdb via the releases/latest permalink, checked each launch, offline-safe (no pinned tag that can 404). - tests: per-font canvas distinctness, solid-readback purity under render-noise, always-present standard-font invariant, no duplicate families.
15 KiB
15 KiB
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
Added
timezone="auto": the browser timezone is auto-derived from the egress IP. By default (no explicit timezone) it ALWAYS resolves — from the proxy egress when a proxy is set, otherwise from the host's own public IP — so the zone can never disagree with the IP (the classictimezone_mismatchsignal). An explicit"Area/City"is the only way to force a specific zone. On failure: with a proxy the launch raises (no silent host-TZ fallback behind a foreign proxy); without a proxy it falls back to the host TZ so a transient lookup can't break the launch.- The egress IP is mapped to its IANA zone with an offline mmdb (
daijro/geoip-all-in-one). It always tracks the upstream weekly rebuild: on every launch the current latest release tag is resolved from thereleases/latest/downloadpermalink (no GitHub API → no rate limit) and pulled only if newer than the cache, older copies pruned. Offline → the cached copy is reused; never a pinned tag (daijro prunes old releases, so a pin eventually 404s).STEALTHFOX_GEOIP_MMDBpoints at your own.mmdbto skip the download. resolve_session_timezone(timezone, proxy)andensure_geoip_mmdb()re-exported at the package root (plusGeoTimezoneError) so integrations that own their launch can reproduce the resolution.tests/test_geo.py(37) +tests/test_geoip_update.py(freshness / auto-update / offline fallback) unit tests.- Cross-OS render parity (needs
firefox-12): the same font/canvas/WebGL fingerprint now renders consistently on Windows, Linux and macOS, so a Windows persona looks identical regardless of the host the binary runs on. Each whitelisted font renders a distinct canvas image (font-detection probes that dedup by rendered image keep every name), the standard Windows fonts (Calibri, Franklin Gothic, Gadugi, Javanese Text, Myanmar Text) are always present so the detected font set matches a real Windows install, and the per-seed render-noise leaves a solid-colour reference render byte-exact while still varying real fingerprint renders. - GPU persona applied on every platform: Linux/macOS hosts now present a coherent Windows GPU (renderer + WebGL parameters) instead of the host's real adapter; pool re-rooted on a real-device GPU mix.
tests/test_canvas_render_stealth.py,tests/test_webgl_noise_active.pyand newtests/test_sampler.pycases: regression guards for per-font canvas distinctness, solid-readback purity under render-noise, and the always-present standard-font invariant.
Changed
- Pins
BINARY_VERSION = firefox-12(the build with the cross-OS render-parity patches). - New runtime dependencies:
requests[socks](SOCKS egress lookup),maxminddb(mmdb reader),tzdata(IANA database forzoneinfo, which Windows lacks).
[0.2.0] - 2026-05-28
Added
- Public config helpers in
invisible_playwright.config:get_default_stealth_prefs(seed, *, pin, locale, timezone, extra_prefs, humanize, virtual_display)returns a completefirefox_user_prefsdict;get_default_args()returns the baseline CLI args list (currently empty). Both also re-exported at the package root. invisible_playwright.ensure_binaryre-exported at the package root for parity with thecloakbrowser.download.ensure_binaryintegration pattern that downstream projects (Skyvern, Crawlee, agno) already expect.- These helpers let third-party fetchers (changedetection.io plugins, Crawlee
BrowserPoolsubclasses, agno toolkits) driveplaywright.firefox.launch(executable_path=..., firefox_user_prefs=...)themselves without depending on theInvisiblePlaywrightcontext manager owning the lifecycle. tests/unit/test_config_public.py: 14 unit tests covering deterministic seed, locale / timezone / pin / extra_prefs / humanize variations, and round-trip via the public namespace.
Unchanged
InvisiblePlaywrightcontext manager surface is identical (backwards compatible).BINARY_VERSIONstays atfirefox-7. Python-only release; no new Firefox build.
[0.1.8] - 2026-05-23
Fixed
- #20: cross-origin iframes were unreachable from Playwright.
element_handle.content_frame()returnedNone,frame.evaluate()threw cross-origin SOP errors, andframe_locator(...).click()timed out even withforce=True. Root cause: FF150 defaultsfission.webContentIsolationStrategy=1(IsolateEverything), which site-isolates every cross-origin iframe into a separatewebIsolatedcontent process even whenfission.autostart=False. The parent's Juggler FrameTree then has a Frame placeholder with no docShell and no URL — every protocol op that needs to enter the iframe fails. Fix: pinfission.webContentIsolationStrategy=0(IsolateNothing) in the baseline prefs. The setting can be flipped back per session viaextra_prefs={"fission.webContentIsolationStrategy": 1}.
Added
tests/test_cross_origin_iframe.py: 4 unit + 5 e2e regression sentinels for cross-origin iframe interaction. The e2e layer runs entirely offline against two local HTTP servers on127.0.0.1(two ports = two SOP origins) and coverspage.framesURL tracking,content_frame(),frame.evaluate(),frame_locator(...).locator(...), and end-to-enddispatch_event("click")for plain, sandboxed and titled iframes. A future FF upgrade or fingerprint A/B that flips the pref back to1will fail the suite before shipping.
Unchanged
BINARY_VERSIONstays atfirefox-7. Python-only release; no new Firefox build was needed.
[0.1.7] - 2026-05-21
Fixed
- #18: Tab crash when running with
headless=Trueon Windows on pages that trigger cross-process navigation. Two separate bugs that only manifested together: (1) the Chromium content sandbox at default level 6 puts content processes onkAlternateWinstation, but the wrapper hides the browser window on its own alt-desktop (CreateDesktopfor headless on Windows). Mismatched desktops → cross-process navigations couldn't reparent windows → content process exits cleanly and Playwright firespage.on('crash'). (2) The canvas2dgetImageDatastealth spoof wrote to a read-only mappedDataSourceSurface. On GPU-backed canvases that memory is write-protected → segfault during the finalgetImageDataat page unload. Wrapper now setssecurity.sandbox.content.level=4in the alt-desktop workaround set, andfirefox-7ships the source fix that moves the noise to the JS array's writable backing buffer.
Changed
BINARY_VERSIONbumped fromfirefox-5tofirefox-7.firefox-6was rolled back when its partial fix turned out to be wrong (the iframe-burst hypothesis was a dead end; bisection in the evening found the real two-bug cause documented above).
[0.1.6] - 2026-05-21
Added
profile_dir=kwarg onInvisiblePlaywright(sync + async). When set, the session usesfirefox.launch_persistent_context()so cookies, localStorage, sessionStorage, extensions, cache and prefs are kept on disk between runs.__enter__returns aBrowserContextdirectly:with InvisiblePlaywright(profile_dir=p) as ctx: ctx.new_page(). Pair with a stableseed=to also pin the fingerprint identity across runs. First run creates the dir; subsequent runs reuse it.
Fixed
launch_persistent_context(timezone_id="…")no longer times out at 180s. Root cause:juggler/content/main.jscallsdocShell.overrideTimezone(...)on every navigation; the patched Firefox up to firefox-4 didn't expose that IDL method onnsIDocShell, so the call threwTypeError: docShell.overrideTimezone is not a function. On the non-persistent path the error fired after launch and was harmless; on the persistent path it blocked the launch handshake.firefox-5ships the C++ method (seepatch.mdsection 19); this release removes the firefox-4 era Python workaround that was filteringlocale/timezone_idout of the persistent context kwargs.
Changed
BINARY_VERSIONbumped fromfirefox-4tofirefox-5. The Python source delta is JS/Python only; the new Firefox build adds 50 lines of C++ indocshell/base/nsIDocShell.idl+nsDocShell.cpp.
[0.1.5] - 2026-05-20
Fixed
- #15:
python -m invisible_playwright fetchraisedRuntimeError: no SHA256 for firefox-150.0.1-stealth-linux-x86_64.tar.gz in checksums.txtfor every user because the parser kept the*binary-mode prefix thatsha256sumwrites in front of filenames. Now.lstrip("*")is applied to the key. Reporter + patch: @LostBoxArt. Unrelated to thefirefox-Nbinary; existing caches still work, only first-time fetches were broken.
[0.1.4] - 2026-05-20
Fixed
- #13: every page that threw an uncaught JS error (e.g. bunny.net) crashed the Playwright client with
TypeError: Cannot read properties of undefined (reading 'url'). Root cause: upstream Playwright Juggler added a requiredlocationfield to thePage.uncaughtErrorevent in the 2026-05-07 roll (microsoft/playwright@c8604ec); our fork was carrying the pre-roll schema in everyfirefox-Nbuild. Fix matches upstream — Runtime.js builds theerrorLocation, PageAgent.js forwards it on both worker and runtime error paths, Protocol.js declares the schema field. Reporter: @dionorgua.
Changed
BINARY_VERSIONbumped fromfirefox-3tofirefox-4. JS-only change insidechrome/juggler/;xul.dllandfirefox.exeare byte-identical tofirefox-3.
[0.1.3] - 2026-05-19
Changed
BINARY_VERSIONbumped fromfirefox-2tofirefox-3. The new archives on both Windows and Linux are built from a clean clone of feder-cr/invisible_firefox#stealth/150 — the consolidated source-of-truth fork (renamed fromfeder-cr/firefox; the companionfeder-cr/firefox-stealthpatches repo was deleted, all patches now live as commits on top ofmozilla-firefox/firefox).- The patched Firefox archive now ships the proper C++ implementation of
windowUtils.jugglerSendMouseEvent, replacing the JS shim from 0.1.2.
C++ fixes landed in this release
- C1+C2:
setDownloadInterceptorIDL + cpp (re-landed for FF150). - C4: 5
nsIDocShellstealth attributes (fileInputInterceptionEnabled,overrideHasFocus,bypassCSPEnabled,forceActiveState,disallowBFCache). - C5:
LauncherProcessWin.cpp+nsWindowsWMain.cppjuggler-pipe handle inheritance — without this, the Playwright pipe disconnects immediately on launch. - C6:
juggler-navigation-started-renderer/-browserobserver notifications innsDocShell.cppandCanonicalBrowsingContext.cpp— without these,Page.readynever fires andctx.new_page()hangs. - C7 (partial): storage stub for
nsIDocShell.languageOverride. WorkaroundInvisiblePlaywright(locale="")recommended until full BC FIELD port lands.
Verified
- Both archives built from same source: feder-cr/invisible_firefox commit
68906f1f9c55. - Windows + Linux smoke suite green: launch,
ctx.new_page(),page.mouse.{move,down,up,click,wheel},navigator.webdriver=false, sannysoft 32/33 PASS. - SHA256 published in
checksums.txton thefirefox-3release.
Notes
- This is the first release with a native Linux build of the patched binary (previous
firefox-3draft mentioned shipping the Linux firefox-2 archive byte-for-byte; that no longer applies — Linux now has the full C++ patch series).
[0.1.2] - 2026-05-18
Changed
BINARY_VERSIONbumped fromfirefox-1tofirefox-2. The patched Firefox archive on GitHub Releases now contains the JS fix from 0.1.1 (everypage.mouse.*/page.click()/locator.click()/mouse.wheel()failure on the FF150 binary). Users on 0.1.1 must runpython -m invisible_playwright clear-cache && python -m invisible_playwright fetchto pick up the new archive.
Verified
- Archive integrity tests on both platforms: Windows zip extracted + booted via Playwright (
mouse.move + click + page.click(selector)all succeed end-to-end), Linux tarball file-level checks (firefox/libxul.so sizes, byte-identity of patched JS files against Windows source). 21/21 assertions pass. - SHA256 published in
checksums.txton thefirefox-2release.
0.1.1 - 2026-05-18
Fixed
- Critical: every
page.mouse.*,page.click(selector),locator.click(),page.hover(),mouse.wheel()failed on the patched Firefox 150 binary withwin.windowUtils.jugglerSendMouseEvent is not a function. The Juggler JS was porting calls to a Playwright-specific C++ method that was never landed in the FF146→FF150 port; replaced with the Mozilla chrome-scopewin.synthesizeMouseEventhelper which is present in FF150. Six call sites patched acrossjuggler/protocol/PageHandler.jsandjuggler/content/PageAgent.js. Reporter: @trob9 — #9. _linkedBrowser.scrollRectIntoViewIfNeeded()is now guarded at both call sites inPageHandler.js(dispatchMouseEventanddispatchWheelEvent) — the method is not present on the shipped FF150<browser>element, so the unguarded call threw before the mouse event was dispatched.
Added
tests/test_mouse.py: 12-case regression suite covering every patched code path (mouse.move/click/dblclick/right-click, modifiers, locator.click/hover, wheel, manual mousedown+up, off-viewport move, humanize intermediate moves, scroll-and-click on offscreen element). Test cases inspired bymicrosoft/playwright-python/tests/async/test_click.py.- Community standards:
CODE_OF_CONDUCT.md,CONTRIBUTING.md,SECURITY.md,.github/ISSUE_TEMPLATE/*,.github/PULL_REQUEST_TEMPLATE.md.
Notes
- The Stealthfox humanize Bezier expansion continues to fire intermediate
mousemoveevents; the swap tosynthesizeMouseEventdoes not change the human-trajectory behavior (verified by test). - The reCAPTCHA v3 score (0.90) and FingerprintPro / CreepJS results documented in the README are unaffected —
synthesizeMouseEventis a legitimate Mozilla helper that does not increase the anti-detect surface. - A binary refresh of the patched Firefox archive on GitHub Releases is required for users to receive this fix (the Juggler JS is shipped inside the archive). The
BINARY_VERSIONwill be bumped tofirefox-2in that release.
0.1.0 - 2026-05-13
Added
- Initial public release.
InvisiblePlaywrightsync and async context managers — drop-in replacement forplaywright.sync_api.Browser/async_api.Browser.- StealthFox humanize hook: Bezier-curve mouse trajectories enabled by default.
_fpforgeBayesian fingerprint sampler with ~400 fields per session.- CLI:
invisible-playwright fetch | path | version | clear-cache. - Pinnable fingerprint fields via
pin={...}(seedocs/pinning.md). - SOCKS5 / SOCKS4 / HTTP / HTTPS proxy support with auth.
- Linux x86_64 and Windows x86_64 binary support.