Commit graph

33 commits

Author SHA1 Message Date
Federico
ee0fe57ced
feat: public config helpers for third-party integrations (#25)
Adds invisible_playwright.config module with:
- get_default_stealth_prefs(seed, *, pin, locale, timezone,
  extra_prefs, humanize, virtual_display) -> dict
- get_default_args() -> list

Both also re-exported at the package root alongside the existing
InvisiblePlaywright. ensure_binary is also re-exported there for
parity with the cloakbrowser.download.ensure_binary integration
pattern that downstream projects (Skyvern PR #5340, crawlee-python
PR #1794, agno PR #8129) already expect.

These helpers let third-party fetchers (changedetection.io plugins,
Crawlee BrowserPool subclasses, agno toolkits) drive
playwright.firefox.launch(executable_path=..., firefox_user_prefs=...)
themselves without depending on the InvisiblePlaywright context
manager owning the lifecycle. Same seed semantics, same humanize
toggle, same extra_prefs overlay as the existing wrapper.

Tests: tests/unit/test_config_public.py adds 14 unit tests covering
deterministic seed, locale/timezone/pin/extra_prefs/humanize
variations, and round-trip via the public namespace. Full unit suite
(392 tests) stays green.

Backwards compatible: InvisiblePlaywright surface is unchanged.
BINARY_VERSION stays at firefox-7. Python-only release.
2026-05-28 17:05:22 -07:00
feder-cr
66c6b09821 fix: __version__ comes from package metadata; add --version flag (#24)
Two bugs reported in #24:

1. `python -m invisible_playwright version` printed the literal "0.1.0"
   regardless of the installed version. Root cause: __version__ in
   __init__.py was hardcoded and never bumped when the package version
   moved past 0.1.0. Fix: read from importlib.metadata so __version__
   stays in lockstep with pyproject.toml's `version` field by construction.

2. `python -m invisible_playwright --version` errored with "the
   following arguments are required: cmd". Root cause: the parser had
   `required=True` on its subparsers and no top-level --version flag.
   Fix: add a top-level `--version`/`-V` flag using argparse's standard
   version action, drop `required=True`, and reroute the "no subcommand"
   case through parser.error() so the existing test_no_subcommand_errors
   contract is preserved.

7 new unit tests pin both behaviours so they can't regress silently.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 00:18:03 -07:00
feder-cr
3d8ba0b82c feat: deterministic reCAPTCHA cookie pre-seed via Bayesian browsing history
Adds opt-in helper that auto-injects coherent cookie history into every
BrowserContext created via new_context(). Content is fully deterministic
from the persona seed so a given seed always presents the same cookies
across sessions.

Composition (per persona, all derived from seed):
  - 5 cookies on .google.com (NID, CONSENT, SOCS, _GRECAPTCHA, ENID).
    Excludes 1P_JAR which was deprecated by Google in 2022. CONSENT
    `lang+region` token derived from the persona's IANA timezone
    (Europe/Rome -> it+IT, America/* -> en+FX, etc.). NID prefix
    broadened to 100-540 to cover historical versions.
  - Per-site cookies on 13-25 "visited" everyday domains, sampled from a
    Bayesian network conditioned on gpu_class - workstation/high_end
    personas trend toward dev/tech sites, low_end/integrated_old trend
    toward shop/news/reference. Each site contributes 1-7 cookies based
    on a `cookie_profile` tag. Cookie pool includes _ga, _gid, _clck,
    _clsk, __cf_bm, OneTrust/CookieYes consent, _fbp (Facebook Pixel),
    _dc_gtm_<id> (Tag Manager helper), __hssrc (HubSpot helper).

API:
    Stealthfox(seed=42, prep_recaptcha=True)

No per-call configuration: visited-sites + cookie composition all derived
from the persona seed via the Bayesian sampler.

Gated server-side: forced False if profile_dir is set (persistent profile
owns its own state). All expiries capped to 395 days per Chrome/Firefox
400-day RFC 6265bis-15 limit.

Bayesian integration:
  - New `derive_browsing_history(gpu_class, rng)` in _fpforge/_sampler.py
    (parallel to `derive_font_prefs`).
  - New data files: browsing_pool.json (50 site entries) and
    cpt_browsing_given_class.json (per-class probabilities).
  - Profile dataclass exposes `browsing_history` field.
  - _recaptcha_seed.py consumes Profile.browsing_history; receives
    timezone separately to derive CONSENT lang+region.

Also drops a dead Chromium-only e2e test that always skipped on our
Firefox-only wrapper.

Test coverage: 29 unit tests covering composition, profile recipes
(minimal/ga_only/ga_cf/ga_consent/ga_consent_clarity), determinism,
Chrome 400-day cap, Playwright field requirements, CONSENT lang
mapping (IT/DE/US/default), helper-cookie probability distributions,
end-to-end with real fpforge Profile.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 20:01:26 -07:00
feder-cr
64eef4daff release: 0.1.8 - fix #20 cross-origin iframe regression (pref-only)
Pin fission.webContentIsolationStrategy=0 (IsolateNothing) in baseline
prefs. FF150 ships strategy=1 (IsolateEverything) by default, which
site-isolates every cross-origin iframe into a separate webIsolated
content process even when fission.autostart=False - different from
FF146 Playwright behavior. The parent's Juggler FrameTree then sees
the iframe placeholder with no docShell, no URL and a stale execution
context, so content_frame() returns None, frame.evaluate() throws
cross-origin permission errors, and frame_locator(...).click() times
out. Reproduced with a local cross-origin HTTP harness (two 127.0.0.1
ports = two SOP origins).

The fix is a single pref because that's the level the original Juggler
code paths assume - vanilla Playwright Firefox 146 ran with the looser
default. Disabling site-isolation costs nothing for a single-user
puppet browser; process-per-browser/profile isolation is unaffected.
Caller can A/B per session via
extra_prefs={"fission.webContentIsolationStrategy": 1}.

Tests: tests/test_cross_origin_iframe.py adds 4 unit sentinels (pref
in baseline, survives translate_profile_to_prefs, extra_prefs override
works) and 5 e2e sentinels that spin up two local HTTP servers on
random free ports and verify the four protocol operations that
regressed (page.frames URL tracking, content_frame(), frame.evaluate(),
frame_locator(...).locator(...)) plus dispatch_event('click')
end-to-end, for plain, sandboxed and titled iframes. A future FF
upgrade or A/B flipping the pref will fail the suite before shipping.

Verified clean: pytest -m unit (342 passed), fppro_full.py (ALL
CRITICAL FLAGS CLEAN), fppro_consistency.py (visitor_id stable).

BINARY_VERSION stays firefox-7 - Python-only release.

Issue: https://github.com/feder-cr/invisible_playwright/issues/20

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 10:05:02 -07:00
feder-cr
b98455bf8a test: unblock pre-push hook collection
- pyproject.toml: norecursedirs for tests/playwright-upstream/, a vendored
  Microsoft Playwright test suite with its own pixelmatch API version
  mismatch. We run it explicitly when doing compat audits, not on every
  push. Default collection now ignores it so the pre-push hook (which
  runs the full default pytest collection) doesn't error out.
- tests/test_service_worker.py: replace em-dash with hyphen inside a
  bytes literal at line 91. Python rejects non-ASCII bytes literals
  with SyntaxError at collection time. Now collects cleanly.

Both were blocking unrelated pushes (e.g. the issue #18 fix in the
previous commit). Splitting them out so the issue #18 commit stays
focused.
2026-05-21 20:21:12 -07:00
feder-cr
cf59e98fa9 test: fingerprint surface + consistency e2e tests
96 e2e tests reproducing the canonical anti-bot / fingerprinting
libraries' checks against a local InvisiblePlaywright session
on about:blank (no network).

Surface (28 tests):
  - BotD: webdriver, app_version, UA tokens, function_bind, productSub,
    process, eval.length, languages, plugins, mimeTypes, distinctive
    window/document globals, html attributes, window size, webgl_debug
  - sannysoft: chrome consistency, permissions.query, iframe chrome,
    iframe languages
  - FpJS: canvas 2D, audio offline, color-gamut, color-depth
  - PIN-locked: screen.width/height, hw.concurrency, audio.sampleRate,
    audio.maxChannelCount
  - fpscanner: UA<->platform, no userAgentData on Firefox

Consistency (68 tests):
  - Math determinism: 17 transcendentals + Math.pow
  - Worker scope vs main: 5 navigator props via Blob worker
  - Iframe scope vs window: 4 props + screen
  - UA self-consistency: UA<->platform, UA<->oscpu, UA<->appVersion
  - Native function self-toString: 8 native APIs
  - AudioContext / WebGL determinism
  - Locale<->Intl: DateTimeFormat / NumberFormat / Collator
  - Descriptor shape lies: 16 navigator props (each must be a getter,
    not Object.defineProperty(value=...))
  - performance.timeOrigin + .now() monotonic
  - Window dimension invariants
  - Firefox UA invariants (vendor='', appName='Netscape',
    appVersion short form)

All marked @pytest.mark.e2e so they're excluded from the default
suite that the pre-push hook runs. Invoke explicitly:

    pytest -m e2e -v

Or against a local build:

    INVPW_BINARY_PATH=/path/to/firefox.exe pytest -m e2e -v

Sources: github.com/fingerprintjs/BotD, abrahamjuliot/creepjs,
fingerprintjs/fingerprintjs, antoinevastel/fpscanner,
niespodd/browser-fingerprinting, bot.sannysoft.com.

Verified: 95 passed, 1 skipped (Chromium-only invariant), 0 failed
against firefox-5 local build.
2026-05-21 13:47:14 -07:00
feder-cr
22b1171518 feat: persistent profile dir + C7 closure (firefox-5 / 0.1.6)
- Add profile_dir= kwarg to InvisiblePlaywright (sync + async).
  Maps to firefox.launch_persistent_context(); returns a BrowserContext.
  Cookies / localStorage / extensions / cache / prefs all persisted.

- Drop the firefox-4 era workaround that filtered locale + timezone_id
  out of the persistent kwargs.  firefox-5 ships the C++
  docShell.overrideTimezone IDL method (50 LOC patch in
  docshell/base/nsIDocShell.idl + nsDocShell.cpp, see patch.md
  section 19 in feder-cr/invisible-firefox), so per-realm overrides
  land without crashing the launch handshake.

- Bump BINARY_VERSION firefox-4 -> firefox-5.

- Sentinel unit tests added: persistent kwargs MUST include locale +
  timezone_id (defends against re-introducing the workaround) and
  must NOT include timezone_id when timezone="" is the "host TZ" sentinel.

Validation: smoke test against the local firefox-5 build, persistent
context UP in 21s (was 180s timeout), Intl.timeZone == Europe/London,
hardwareConcurrency / screen / DPR / locale all reflect the PIN.
2026-05-21 12:19:38 -07:00
feder-cr
5f0ba5d659 test: fortress coverage for download + constants + e2e
#15 shipped because unit tests only covered text-mode sha256sum output.
This adds a comprehensive parser test matrix (binary mode `*` prefix,
mixed, CRLF, BOM, indent, trailing whitespace, multiple stars, empty,
comment-only, sha256sum -b coreutils format) plus the integration
sentinel test_ensure_binary_accepts_binary_mode_checksums that
reproduces #15 against the live wire format.

Also covered for the first time:
- _resolve_asset_url public/private branches, auth header propagation,
  asset-missing failure, HTTP 4xx propagation
- _download_file 200/404/500, parent mkdir, auth on api.github.com
  only (not leaking to CDN URLs)
- cache_root / cache_dir_for_version path shape and version isolation
- _parse_owner_repo malformed inputs and dash/underscore/dot repo names

ARCHIVE_NAME case-matrix (uppercase platform, lowercase machine),
unsupported arch rejection (i386, ppc64le, arm64), unsupported platform
rejection (darwin, freebsd), BINARY_ENTRY_REL <-> ARCHIVE_NAME invariant,
RELEASE_URL_TEMPLATE shape (https, placeholders, owner pointer).

New e2e tests (marker `e2e`, excluded by default):
clean venv install, fetch against live release, binary launch, real-site
Playwright sanity. This is the test suite that would have caught #15
end-to-end before publish.

Stats: 275 -> 327 unit tests (+52), 0 -> 6 e2e tests.
Controprova: rolling back the parser fix makes 9 of the new tests fail
with the exact "no SHA256 for ..." error from #15.
2026-05-20 12:20:11 -07:00
feder-cr
589c848e07 fix: every mouse action failed on FF150 — jugglerSendMouseEvent was never landed (#9)
The Juggler JS in upstream Playwright calls win.windowUtils.jugglerSendMouseEvent
at four sites, but when the Juggler was ported FF146 -> FF150 the matching C++
patch to nsIDOMWindowUtils.idl + nsDOMWindowUtils.cpp was dropped. Result: every
page.mouse.*, page.click(selector), locator.click(), page.hover(), mouse.wheel()
threw "win.windowUtils.jugglerSendMouseEvent is not a function" on first call.

The fix is shipped in the patched Firefox source (feder-cr/firefox-stealth):
six call sites in juggler/protocol/PageHandler.js and juggler/content/PageAgent.js
were swapped to win.synthesizeMouseEvent — a Mozilla chrome-scope helper that is
already present in FF150. scrollRectIntoViewIfNeeded was also guarded at the two
PageHandler.js sites where it was called unconditionally on the FF150
_linkedBrowser, which no longer exposes that method.

This invisible_playwright release adds the regression suite in tests/test_mouse.py
(12 cases inspired by microsoft/playwright-python/tests/async/test_click.py),
the CHANGELOG, and the version bump. The patched Firefox archive on GitHub
Releases must be refreshed before users actually receive the fix; the
BINARY_VERSION bump to firefox-2 will land with that asset.

Reporter: @trob9 (issue #9) — provided ready-to-apply JS patches, 4-line minimal
repro, and confirmed reCAPTCHA v3 = 0.90 holds after the swap.
2026-05-18 14:45:01 -07:00
feder-cr
07701a901d Merge pull request #2 from christianbaumann/main
Add comprehensive test suite (270+ tests across 14 files)

- Bayesian network primitives (25 tests)
- fingerprint sampler (55 tests)
- Profile dataclass + pin system (43 tests)
- configure_proxy decision table (24 tests)
- Windows + platform-agnostic prefs (27 tests)
- CLI / download gap coverage (17 tests)
- Multi-module integration (12 tests)
- E2e launcher lifecycle (9 tests)
- launcher / headless / async_api (32 tests)
- Linux-specific prefs / headless (16 tests)
- Linux tar.gz download (4 tests)
- Linux integration pipeline (3 tests)
- Linux launcher e2e (4 tests)
- pytest markers + shared conftest

Resolves conflicts in pyproject.toml, test_prefs.py, test_proxy.py by
keeping the upstream additions and merging with the previous wheel-build
fix. 323 tests pass on Windows; 14 e2e tests deselected by default
(require patched Firefox binary).
2026-05-16 17:14:08 -07:00
feder-cr
3d303a4915 tests: add wheel regression — fail if wheel has duplicate zip entries 2026-05-16 10:39:40 -07:00
feder-cr
9de222aa15 tests: add/update tests/test_prefs.py 2026-05-15 20:02:01 -07:00
feder-cr
93da245b8a tests: add/update tests/test_cli.py 2026-05-15 20:02:00 -07:00
feder-cr
fbfb4fc8c4 tests: add/update tests/test_launcher_config.py 2026-05-15 20:01:58 -07:00
feder-cr
03f8453398 tests: add/update tests/test_pin.py 2026-05-15 20:01:56 -07:00
feder-cr
4f38b2ec29 tests: add/update tests/test_fpforge.py 2026-05-15 20:01:55 -07:00
feder-cr
67e2824876 tests: add/update tests/test_proxy.py 2026-05-15 20:01:54 -07:00
feder-cr
508cb0f59d tests: add/update tests/test_imports.py 2026-05-15 20:01:53 -07:00
chrissbaumann
70c1ca464f test(e2e): add 4 Linux launcher-routing tests for Phase 9
E9-E12 exercise the launcher's Linux code paths without spawning a
real Firefox binary or Xvfb. They monkeypatch ``sys.platform`` and
stub ``make_virtual_display`` / ``_binary_on_path`` so the tests run
on any host:

- E9 ``_build_prefs(headless=True)`` on Linux passes
  ``virtual_display=False`` to the translator, so the Win32-only
  ``security.sandbox.gpu.level`` workaround never leaks into Linux
  prefs (Xvfb handles window hiding instead).
- E10 ``_resolve_headless`` on Linux + headless=True invokes the
  dispatcher and stores the returned object on ``self._virtual_display``.
- E11 ``_teardown`` stops the Linux virtual display, clears the
  reference, and is idempotent on a second call.
- E12 With Xvfb missing from PATH, ``_resolve_headless`` raises a
  clear ``RuntimeError`` mentioning ``Xvfb`` instead of a cryptic
  FileNotFoundError.

Suite on Linux/WSL: 286 passed, 5 skipped (4 binary-gated E2E
lifecycle tests + 1 Win32 ctypes test). Binary-gated E1/E2/E5/E8
remain ready to run on Linux once the patched Firefox tar.gz is
fetched locally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 14:07:03 +02:00
chrissbaumann
b8139c2873 test(integration): add 3 Linux pipeline tests for Phase 8
IT11–IT13 mirror IT10 on the Linux platform branch, verifying:
- Xvfb workarounds coexist with SOCKS5 proxy mutation
- MSAA pin propagates through prefs translation on Linux
- _LINUX_GENERIC_FONT_FACTORS is prepended to per-font metrics

Tests use monkeypatch on sys.platform so they run on any host OS.
Verified green on Linux/WSL alongside the existing Windows tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 13:53:24 +02:00
chrissbaumann
a3353fc861 test(download): add 4 Linux tar.gz download tests for Phase 7
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 13:40:42 +02:00
chrissbaumann
d392ca2971 test(prefs, headless): add 16 Linux-specific tests for Phase 6 + 10
Cover the Linux branches in prefs.py that previously had no tests
(font metrics, GPU spoofing, MSAA from profile, canvas noise mask
per renderer, WebGL extension preservation, Xvfb workarounds,
virtual_display no-op) and add construction smoke tests for
_LinuxVirtualDisplay. Also fix two host-platform-dependent tests
so the suite stays green on both Windows and Linux.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 13:21:17 +02:00
chrissbaumann
4f6254469e test(launcher, headless, async_api): add 32 Phase 10 gap-coverage tests
Final sweep adds unit tests for the modules left at 0% direct coverage
after Phases 1-9:

- launcher._tz_env: 7 tests covering the IANA -> POSIX mapping
  including the Phoenix / Honolulu no-DST regression cases
- launcher._humanize_max_seconds, _default_context_kwargs: 11 tests
  on the constructor-side helpers (no browser launch)
- _headless.make_virtual_display dispatcher + _WindowsVirtualDesktop
  init/teardown: 8 tests (Linux dispatch branch covered without
  spawning Xvfb, since __init__ does no I/O)
- async_api.InvisiblePlaywright constructor parity with sync: 8 tests
  guarding against drift between the two APIs

Suite: 230 -> 264 passing. Pyramid stays clean: 243 unit / 12
integration / 9 e2e.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:59:47 +02:00
chrissbaumann
234fe7e406 test(e2e): add 9 launcher lifecycle tests for Phase 9
Five test the constructor only (seed handling, eager profile build,
fail-fast pin validation) and always run. Four spin up the patched
Firefox and exercise the full `with InvisiblePlaywright(...)` lifecycle,
gated on a locally cached binary so CI without the binary skips
cleanly. All 230 tests pass on Windows with the binary fetched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:52:46 +02:00
chrissbaumann
9c8d24408b test(integration): add 12 multi-module pipeline tests for Phase 8
Covers profile->prefs end-to-end, SOCKS/HTTP proxy + prefs composition,
pin propagation, seed determinism/variation, font whitelist passthrough,
dark/light theme palette overlay, and a Windows-specific virtual_display
+ SOCKS combo. Linux-specific branches stay covered by their unit tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:44:46 +02:00
chrissbaumann
ca8d815216 test(cli, download): add 17 gap-coverage tests for Phase 7
CLI: clear-cache (existing + missing), path (ok + error), fetch happy
path, no/unknown subcommand error paths. Calls cli.main() directly
instead of subprocess to keep tests fast and capture stderr cleanly.

Download: cache hit skips HTTP, tar.gz extraction, comment/blank
checksum lines, unknown archive format, missing entry after extract,
unsupported platform. Also covers pure helpers _parse_owner_repo,
_sha256_file, and _github_token env precedence.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:35:57 +02:00
chrissbaumann
54ae310bf2 test(prefs): add 27 Windows + platform-agnostic gap tests
Covers _accept_language, _font_metrics_for_platform, Windows GPU/MSAA
clearing, Windows canvas noise mask (intel path), Windows WebGL extension
clearing, timezone handling, extra_prefs overlay (add/delete/override/no-op),
dark-theme system colors palette, locale normalization, Xvfb-key absence on
Windows, virtual_display sandbox workaround, and seed-derived LAN IP.

Linux-specific branches are intentionally not covered in this commit per
scoping instruction; they remain available in the plan for a follow-up
pass when running on Linux.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:30:46 +02:00
chrissbaumann
074b4b3274 test(proxy): add 24 unit tests for configure_proxy decision table
Covers every input partition: None/empty/direct, SOCKS4/5/default,
HTTP/HTTPS passthrough, case-insensitive scheme detection, malformed
inputs, mutation contract, and edge cases (IPv6 brackets, whitespace,
non-numeric ports).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:24:57 +02:00
chrissbaumann
38ae41289d test(profile): add 43 unit tests for Profile dataclass and pin system
Covers _validate_pin_key (all groups + negatives), _apply_pins_to_raw
(fonts list/tuple/typeerror, multi-pin, no-mutation, unknown-key guard),
and generate_profile (determinism, seed coercion, pin propagation through
to_prefs_dict, frozen-instance, dark_theme bool coercion, fonts list
roundtrip, int31 boundary). Includes a guard test that every dotted pin
key has a _PIN_TO_RAW mapping.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:46:09 +02:00
chrissbaumann
3286123b11 test(sampler): add 55 unit tests for fingerprint Bayesian sampler
Covers classify_gpu (decision-table over 28 GPU strings inc. boundary
values for AMD Radeon number ranges), _screen_tier resolution
classification, derive_font_prefs / derive_font_whitelist coherence and
determinism, and the public Forge / sample entry points (locked
identity, key set, type correctness, seed determinism).

One plan deviation: the original plan claimed `AMD FirePro W7100` →
`workstation`, but the workstation regex requires a `Radeon` prefix,
so FirePro alone falls through to the `mid_range` fallback. Test
asserts the actual behaviour.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:35:24 +02:00
chrissbaumann
8709ef77d2 test(network): add 25 unit tests for Bayesian network primitives
Covers _weighted_pick, _parent_key, _topsort, Node.sample, Network.sample
following ECP, BVA, and error-guessing techniques from the plan.
2026-05-14 11:24:57 +02:00
chrissbaumann
957f84d9a5 test: add pytest markers, conftest, fix Windows-incompatible existing tests
- Add tests/conftest.py with deterministic_rng + sample_profile fixtures
- Register unit/integration/e2e markers in pyproject.toml
- Mark existing 14 tests as @pytest.mark.unit
- Fix test_cli.py: use 'invisible_playwright' (underscore) for 'python -m'
- Fix test_translate_includes_gpu_renderer: assert Windows behavior (empty renderer)
2026-05-14 11:21:10 +02:00
feder-cr
7a983e99c5 feat: initial public release
invisible-playwright: a patched Firefox 150.0.1 for browser-fingerprint
stealth, shipped as a Playwright-compatible Python wrapper.

  * Sync + async InvisiblePlaywright launcher (firefox_user_prefs, virtual
    desktop on Windows, SOCKS5 auth via patched nsProtocolProxyService)
  * fpforge: Bayesian fingerprint sampler over GPU / audio / fonts /
    screen / ~400 other navigator fields
  * WebRTC stealth: srflx address swap, synthetic srflx fallback,
    private-LAN host candidates. No real public IP leak via STUN.
  * GPU sandbox fix for FF150 alt-desktop regression
  * Bezier-curve mouse motion baked into Juggler

Targets Windows x86_64 + Linux x86_64. Binary fetched on first run from
GitHub Release "firefox-1".
2026-05-12 22:32:58 -07:00