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)
| File | Size | Uploaded | |
|---|---|---|---|
| gecko_web_runtime_client-1.1.1.tar.gz | 54.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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