Skip to main content

Python client

The client provides a standard-library core plus an optional Loguru-backed diagnostics layer. From this directory:

$env:PYTHONPATH = "$PWD"
python ..\examples\normal_navigation.py

The package resolves runtime/gecko-web-worker.exe relative to its own bundle. Override paths with WPR_RUNTIME_HOME, WPR_RUNTIME_DIR, WPR_WORKER_EXE, WPR_PROFILE_ROOT, or WPR_LOG_ROOT when embedding it in a larger application.

Firefox Necko network client

The version-neutral wpr-http-v1 API is exposed by gecko_web_runtime.AsyncWprHttpClient:

from gecko_web_runtime import AsyncWprHttpClient

async with AsyncWprHttpClient() as client:
    response = await client.get("https://example.com/")
    html = await response.atext()

The selected Firefox bundle launches runtime/net-v155/gecko-net-worker.exe (the versioned adapter may be replaced by a later bundle). Its response body uses shared memory and is released when atext(), aread(), or aclose() completes. Set WPR_RUNTIME_HOME, WPR_RUNTIME_DIR, and WPR_NETWORK_WORKER_EXE to select a different Firefox-version adapter.

To install the pinned runtime automatically from the GitHub Release:

python -m gecko_web_runtime install-runtime --version 155

The command verifies the pinned SHA256 and stores the selected runtime under %LOCALAPPDATA%\WPR\runtime\155.

For development, use uv from this directory so the Python environment and lock file are reproducible:

cd G:\wpr-runtime-155-win64\python
uv sync --extra diagnostics
uv run python -m unittest discover -s tests\unit -v

The Gecko binary is intentionally not a Python dependency. Install or select the matching runtime separately after the environment is ready:

uv run python -m gecko_web_runtime install-runtime --version 155

Live network workflow tests are opt-in:

$env:WPR_RUN_ONLINE_TESTS = "1"
uv run python -m unittest discover -s tests\integration -v

To measure cold/warm navigation and the current isolation boundary:

uv run python tests\integration\context_reuse_benchmark.py `
  --url https://example.com/ `
  --out context-reuse.json

The benchmark records first/second navigation timing, frame remote types, WindowGlobal replacement, Worker PIDs and whether an isolated context sees a Cookie from the persistent context.

An optional per-Worker fpfile path can be passed to the session. The Worker reads the file before creating the remote page; its Firefox profile remains a separate Cookie/Storage directory:

async with AsyncGeckoWorkerSession(
    fpfile=r"G:\browser-runtime\fpfile.txt"
) as session:
    await session.page_create()

For application code, prefer the high-level runtime facade and workflow adapter. Frame handles, pointer coordinates, WindowGlobal rebinding and challenge waits remain internal:

from gecko_web_runtime import AsyncGeckoRuntime

async with AsyncGeckoRuntime(fpfile=r"G:\browser-runtime\fpfile.txt") as runtime:
    page = await runtime.new_page()
    result = await page.navigate(
        "https://nopecha.com/demo/cloudflare",
        workflow="turnstile",
    )
    print(result.ok, result.url, len(result.html))

For WeChat public-account articles, use the site adapter instead of the Cloudflare-specific Turnstile workflow:

async with AsyncGeckoRuntime() as runtime:
    page = await runtime.new_page()
    result = await page.navigate(article_url, workflow="wechat_article")
    if result.ok:
        article_html = result.html

Use WorkflowMetrics when an application needs a stable result/metrics boundary. The default output contains the product chain stages (T0...T9) plus a compact report with success, final URL, HTML size, total/navigation/final-ready time, and parent/whole-process-tree memory peaks. Detailed attempts, phase timings, and per-stage resource snapshots are emitted only with debug=True or emit="debug":

from gecko_web_runtime import WorkflowMetrics

metrics = WorkflowMetrics(name="wechat", emit="summary", print_summary=True)
summary = metrics.emit(result)

Library code can set emit="none" and consume the returned dictionary without printing. WPR_METRICS_EMIT, WPR_METRICS_LOG_LEVEL, WPR_METRICS_DEBUG, WPR_METRICS_PRINT, and WPR_METRICS_MEMORY provide process-level defaults.

The adapter recognizes the WeChat/Tencent gate, rebinds the current top WindowGlobal, and dispatches a real pointer sequence to the visible verification target. It reports slider/image challenges as a bounded result for a future dedicated solver rather than treating the challenge page as an article. It is one-shot by default and closes the Page after the workflow boundary; pass WechatArticleWorkflow(close_after=False) when intentionally reusing the Page.

For multiple logical sessions, keep the Worker runtime alive but make the storage boundary explicit:

async with AsyncGeckoRuntime(fpfile="fpfile-a.txt") as runtime:
    async with runtime.new_context(isolation="persistent") as context_a:
        page_a = await context_a.new_page()
        result_a = await page_a.navigate(url_a)

    async with runtime.new_context(isolation="isolated") as context_b:
        page_b = await context_b.new_page()
        result_b = await page_b.navigate(url_b)

persistent reuses the runtime's current Worker while each Context receives its native Firefox OriginAttributes boundary (user_context_id and optional private_browsing_id). isolated remains the explicit separate Worker and profile mode for callers that require process-level isolation.

Turnstile results expose phase timings in result.timing_ms, including per-attempt iframe/action waits, POST, redirect, final Document readiness, and HTML serialization. Worker PID, Working Set, Private Bytes, and CPU samples are available in result.resource_usage. Sampling can be disabled for a low-overhead benchmark with TurnstileWorkflow(resource_sampling=False) or WPR_RESOURCE_SAMPLING=0. The integration test writes the complete result to the path in WPR_RESULT_OUT when set.

Challenge retries use the adaptive policy by default. After a top-level state transition it waits for the network settle window and stops immediately on POST/redirect; it only dispatches another action when no submit arrives. retry_policy="legacy" preserves the previous retry loop for A/B experiments, while retry_policy="generation" is a strict diagnostic policy that requires a new BrowsingContext/WindowGlobal before another action. The third-party client exposes the same switch as --retry-policy. Debug results include state_change_to_submit_ms when both observations were captured on the same client monotonic clock.

The final boundary is configurable. final_wait_until="complete" waits for the full DOM/load boundary and is the compatibility default. Set WPR_TURNSTILE_WAIT_UNTIL=document (or pass final_wait_until="document") when the caller only needs the final Document HTML; the result then reports final_document, final_load, and the selected final_ready boundary separately. Document mode does not wait for the page's scripts, stylesheets, images, or analytics resources to finish.

Large results use a separate data plane. page.eval_shared_blob() uses a one-shot mapping, while page.eval_shared_ring()/page.html_shared_ring() use a Worker-lifetime fixed-slot ring. Both return a small descriptor over the control pipe and a read-only Windows named mapping for the bytes. Read it as a memoryview or decode it with read_text(), then release the lease explicitly:

blob = await page.html_shared_ring()
try:
    html = blob.read_text()
finally:
    await blob.release()

This keeps multi-megabyte HTML out of JSON serialization and the named-pipe response. The ring mapping is created once per Worker and reuses slots using generation-bearing leases; data.release returns a slot to the ring. Set WPR_HTML_TRANSPORT=json, blob, or ring to A/B the adapter boundary. The WeChat and Turnstile adapters default to ring and fall back to ordinary page.eval when an older Worker has no data-plane method.

The long-lived comparison probe keeps one Worker per site/transport, uses a fresh OriginAttributes context for every sample, and records success rate, P95, CPU, Worker/process-tree memory, and Gecko reporter stages:

uv run python tests\integration\data_plane_ab_benchmark.py `
  --runs 10 --modes json ring

The low-level AsyncGeckoWorkerSession API remains available for custom workflows and backward compatibility. Turnstile is implemented in gecko_web_runtime.workflows.turnstile; future site adapters belong in the same package and are not part of the Gecko core.

The client project keeps its tests alongside the package source:

python/tests/unit/          # import/API contract tests
python/tests/integration/   # opt-in live Worker/workflow tests

The larger G:\browser-runtime\tests\probes tree is a separate black-box runtime audit harness. It exercises the complete bundled Gecko runtime and stores diagnostic artifacts, so it is intentionally not included in the Python wheel.

To enable structured application diagnostics:

pip install gecko-web-runtime-client[diagnostics]
from gecko_web_runtime.diagnostics import configure_logging

logger = configure_logging(log_file="runtime.log")
logger.info("application.start")

For a real page WebRTC permission boundary, use the same session and answer the native pending request. The Worker forwards Firefox's PeerConnection:response:allow or PeerConnection:response:deny topic; it does not manufacture SDP, ICE candidates, or media devices:

pending = await session.page_permission_requests()
for request in pending:
    await session.page_permission_respond(request["callID"], "allow")

Leaving the list unanswered preserves Firefox's normal prompt-pending behavior. A response is scoped to the current WindowGlobal, so a navigation that replaces it requires polling the new page's request list.

For a private GitHub Release, set GITHUB_TOKEN, GH_TOKEN, or WPR_GITHUB_TOKEN, or configure Git Credential Manager for the GitHub account.

Firefox Necko network client

The version-neutral wpr-http-v1 API is exposed by gecko_web_runtime.AsyncWprHttpClient:

from gecko_web_runtime import AsyncWprHttpClient

async with AsyncWprHttpClient() as client:
    response = await client.get("https://example.com/")
    html = await response.atext()

The selected Firefox bundle launches gecko-net-worker.exe. Its response body uses shared memory and is released when atext(), aread(), or aclose() completes. Set WPR_RUNTIME_HOME, WPR_RUNTIME_DIR, and WPR_NETWORK_WORKER_EXE to select a different Firefox-version adapter.

Metadata

Release files for gecko-web-runtime-client 1.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gecko-web-runtime-client 1.1.1
File Size Uploaded
gecko_web_runtime_client-1.1.1.tar.gz 54.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gecko-web-runtime-client 1.1.1
File Interpreter ABI Platform
gecko_web_runtime_client-1.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 114.1 kB

Release files / gecko_web_runtime_client-1.1.1.tar.gz

Download URL gecko_web_runtime_client-1.1.1.tar.gz
Size 54.9 kB
Tags Source
SHA-256 checksum
How to use checksums
92639722ce25d0683af5d7ad70cc1a9c8e4164ac9d3245d3ec2de68b8b4d50b5
BLAKE2b-256 checksum
How to use checksums
06ebcc78f2be512b96a06ea8388ed72a668f0a11f4cc9ebb57e9638b98a24b1e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / gecko_web_runtime_client-1.1.1-py3-none-any.whl

Download URL gecko_web_runtime_client-1.1.1-py3-none-any.whl
Size 59.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
945f291987938b9cb42099b0b4b5d49ce9b4aaadec77abda15678ec645237f15
BLAKE2b-256 checksum
How to use checksums
5b1531e69141dca7685f19b4e136b083cd77cdb8f00401f2745fe652f46c1881
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release history Release notifications | RSS feed

1.4.2

2 release files

1.4.1

2 release files

1.4.0

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.0

2 release files

This release

1.1.1 This release

2 release files

1.1.0

2 release files

1.0.1

1 release file

1.0.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page