· via dev.to (home feed)
myjs is a pip-installable JavaScript interpreter for Python, no Node or browser required
myjs, introduced on dev.to, is a pip-installable JavaScript interpreter for Python: it runs scripts, renders HTML headlessly, scripts the DOM and reaches Python packages and C libraries without Node or a browser.

A post on dev.to introduces myjs, a JavaScript interpreter written in Python and distributed as a pip package. According to the post, it runs .js files, renders HTML pages headlessly, scripts the DOM, calls native C libraries through an ffi layer, and reaches the wider Python ecosystem from JavaScript — with no Node runtime, no browser and no build step.
A pip-installable runtime
The tool installs with pip, or with pipx for an isolated CLI. The myjs command opens a REPL with persistent readline history, reverse search, TAB completion, auto-detected multi-line input and top-level await. The same binary runs script files (extra arguments arrive as globalThis.argv), evaluates snippets via -e, and headlessly renders .html files, writing the resulting HTML to stdout or to a file. A --strip-scripts flag removes script elements after they execute, and an optional myjs[gui] extra can display the rendered DOM in a native window. Bundled demos ship with the package, including a live terminal dashboard called cockpit with killable workers and raw keypress handling.
The Python-side API
From Python, myjs.eval evaluates expressions, myjs.run executes files, and myjs.Session creates an isolated global scope — the post shows one session evaluating a variable and reading it back in a later eval call. Sessions accept an initial scope dictionary, capture console.log output on a console_lines attribute, and translate escaping JavaScript exceptions into myjs.JSError objects carrying the original name, line number and call stack. myjs.import_js goes further, loading a .js file as a Python module whose exported functions become directly callable — the example imports a doubling function and calls it from plain Python.
Web platform coverage
Scripts see document, window and roughly 190 constructors, among them URL, Headers, Event, DOMRect and TextEncoder, enough to build real DOM trees with createElement and appendChild. The event loop supports Promise combinators, async/await, setTimeout, setInterval and queueMicrotask, with microtasks drained before timers. fetch is asynchronous and thread-backed, so awaiting Promise.all over several fetches is genuinely concurrent, and WebSocket is described as a real RFC 6455 client.
Node-flavoured fs, path, sh, http, os and process modules cover file I/O including raw byte reads, shell commands, environment access and a small HTTP server, while a pre-imported struct module parses binary headers such as BMP, PNG and ELF without extra libraries. console implements %s, %d and %c formatting plus table, group, count, time and assert. On macOS, scripts can reportedly drive native dialogs such as prompt, confirm and file pickers, read and write the system clipboard, and use say, notify, hash, atob/btoa and localStorage.
Bridges into Python and C
A py object evaluates Python from JavaScript and imports packages such as pandas or sqlite3, and in ES modules a bare specifier resolves to a Python module — the post's example is importing numpy. The ffi module loads C libraries through ctypes with no node-gyp and no compiler; the demo loads libc, declares argument and return types for abs, and calls it.
For headless rendering, myjs.Page.load accepts a local path or an http(s) URL, fetches the page plus its CSS and scripts, folds the CSS into the document so getComputedStyle sees the rules, gives module scripts module semantics, and fires DOMContentLoaded and load. Pages expose eval, fill, submit, wait_for and text for automation, and myjs.render performs server-side rendering in one call. The post frames this as Puppeteer-style automation delivered by a pip install instead of a 150 MB Chromium download.
How it's built
myjs is a runtime layer over the domonic-libs port of the acorn parser: a tree-walking evaluator plus a code generator that can move JavaScript from source to AST and back, running on domonic's DOM and shipping in lockstep with domonic-libs. The language layer is said to pass a curated test262-style battery covering closures, classes, destructuring, generators, async/await, prototype chains, Symbol and the core built-ins; Proxy and with are explicitly not covered. The project is MIT licensed, with a full reference in its documentation.
Why it matters
Running JavaScript from Python today usually means installing Node alongside it, and touching a rendered DOM typically means downloading headless Chromium. myjs proposes a third path: a single dependency that interprets the language, emulates enough of the web platform for scraping and server-side rendering, and opens two-way traffic with Python's package index and native C libraries. That footprint is attractive for scripting, testing, gluing JavaScript into data pipelines, or locked-down environments where a full toolchain is impractical. The caveats deserve weight, though: every capability above is described in the project's own dev.to post rather than by independent reviewers, the language layer skips Proxy and with, and a tree-walking interpreter will not match V8 on raw speed. As a lightweight bridge between two very large ecosystems, it is still a distinctive addition to the Python tooling shelf.
- #javascript
- #python
- #interpreter
- #developer-tools
- #open-source