Skip to content
losenine edited this page Oct 31, 2026 · 2 revisions

English · 中文

FAQ

General

What Python versions are supported?

64-bit Python 3.10 and above on Windows x64, macOS arm64 and Linux x86_64, tested up to Python 3.14. On macOS the Necko helper runs on the interpreter that installed ruyijs; the Linux wheel brings its own Python 3.14 for it.

Does it work on macOS or Linux?

Yes. Since 0.3.0 PyPI carries a macosx_26_0_arm64 wheel (macOS 26 or later; no proxy support yet) and a manylinux_2_39_x86_64 wheel (glibc 2.39 or later). See Installation, docs/macos.md and docs/linux.md.

The JS engine is Mozilla's official SpiderMonkey and the network stack is Mozilla's official Necko; both are built from the official Firefox source, referenced as the firefox/ submodule.

Do I need to download a browser?

No. Every wheel bundles the SpiderMonkey + Necko runtime built from the Firefox 159.0 source, and pip install ruyijs needs no browser. On macOS, pip also installs the Python packages of the Necko helper.

Is there a window, a screenshot API or rendering?

No. ruyiJS has no browser window and no full page layout or rendering; it is a JavaScript + Web API environment for automation, analysis and research. Canvas 2D still draws through Firefox's own Skia.

Is ruyiJS the right tool for every page?

If a plain HTTP client already gets your pages, you don't need it. ruyiJS is for pages whose JavaScript — challenges, signatures, fingerprints — has to actually run.

Troubleshooting

Context hangs or doesn't respond

  • Use the with statement (with Context() as ctx:) so the process is cleaned up properly.
  • If you use a proxy, verify that it is reachable: Context(proxy="http://127.0.0.1:7890").
  • Increase the timeout: Context(timeout=60). It applies to startup and to every single call.
  • Page work only progresses while you call advance(). A fetch() or navigate() that never seems to finish usually needs more advance() calls.
  • On Wine, use 0.1.5 or later, which fixes a known navigate deadlock. Since 0.1.7, Context also sets the per-program Wine override HKCU\Software\Wine\AppDefaults\js.exe\DllOverrides to msvcp140=native,builtin (an existing value is kept; native Windows is untouched), which fixed external scripts, stylesheets and preloads hanging under Wine.

JSError — the script threw

The site's JavaScript threw an exception. Inspect error.name, error.message and error.stack to locate the cause. If the page relies on an API that is not implemented yet, the stack points at the missing call. A JSError does not close the context; in loops, the examples wrap advance() in try/except JSError and keep going.

RuntimeError: ruyijs Context is closed

The context was closed — by close() or the end of its with block, or automatically after a timeout or a broken pipe (the binding then kills the process). Create a new Context.

TimeoutError

A call took longer than timeout, or an exposed Python callback did not return in time (ruyijs host callback timed out). The context is closed afterwards. Raise timeout, advance in smaller steps, or keep callbacks short.

BrokenPipeError: ruyijs process exited (code N): ...

The shell process exited while starting. The message carries its exit code and the end of its stderr.

FileNotFoundError: ruyijs runtime is missing ...

No runtime was found. Install the platform wheel, build the runtime from source, or set RUYIJS_SHELL to an existing executable; the message lists the paths searched. ruyijs shell does not exist: ... or RUYIJS_SHELL does not exist: ... means the path given by shell= or RUYIJS_SHELL is wrong.

OSError: ruyijs requires Windows x64, macOS arm64 or Linux x86_64

The platform is not supported (for example 32-bit Windows, Intel macOS or Linux on ARM).

ReentrantError

An exposed Python callback tried to call the same Context (for example context.eval) while JavaScript was waiting for that callback. Return a value instead and make the follow-up call after the callback has returned.

ValueError: ruyijs request exceeds 16 MiB

A single call — the code you evaluate or a value passed to set() — exceeds the 16 MiB frame limit. Split it into smaller calls. The context stays open.

The page reports a different Firefox version than the TLS handshake

tls= changes only the network fingerprint. Set a matching navigator.userAgent with configure_fingerprint; see Network and TLS and Fingerprint and Environment.

Usage

How do I use a proxy?

with Context(proxy="http://127.0.0.1:7890") as ctx:
    ctx.navigate("https://example.com/")

Proxies are set per context. The Context docstring describes proxy as an explicit HTTP(S) proxy URL; the README also lists SOCKS5. None or "" connects directly.

How do I run the examples?

python -m ruyijs.examples              # list all examples
python -m ruyijs.examples akamai --proxy http://127.0.0.1:7890
python -m ruyijs.examples creepjs

See Examples.

How can I see which browser APIs a page touches?

Create the context with mode="debug" and read get_api_log() (drains the log) or peek_api_log(). Only members registered by a production installer are recorded.

Where do console messages go?

context.console_log() returns them oldest first; the buffer is a bounded ring that keeps the newest records. console_log(clear=True) reads and drains in one step.

How do I report a bug or a vulnerability?

For bugs, open an issue with the ruyijs version or commit, your Windows version (or macOS and Xcode versions), a minimal script, the actual output and, where possible, what real Firefox returns — see Contributing and License. For vulnerabilities, do not open a public issue; follow SECURITY.md.

Clone this wiki locally