Skip to main content

Drive and observe a live browser session from Python, with bidirectional async events.

Project description

loominum

A Python library for driving and observing a live browser session from Python code, with bidirectional async event flow. Python pushes JavaScript into the page; the page emits events back.

Two transports

  1. JS-injection mode (working today) — a one-time paste-bootstrap opens a WebSocket from the page back to the Python server. Site-agnostic, no Chrome flags, but bootstrap is manual and injection dies on navigation unless re-pasted.

  2. CDP sidecar mode (working today, via the lum-cdp console script) — a Python sidecar speaks Chrome DevTools Protocol to a CDP-enabled browser and impersonates a browser to the Loominum server. Gives nav-surviving injection (Page.addScriptToEvaluateOnNewDocument) and CAPTCHA-safe trusted-event dispatch (Input.dispatchKeyEvent / dispatchMouseEvent). Requires the browser launched with --remote-debugging-port.

Same lum.exec / on / add_init / navigate API across both transports.

Use cases

  • Authenticated API automation (call APIs in browser context with session cookies)
  • Scrape orchestration with DOM-event triggers
  • Download monitoring (watch DOM for ready-links, hand off filenames to Python)
  • Form automation
  • Interactive Python-REPL → browser debugging

Status

  • src/loominum/ — JS-injection implementation. Site-agnostic API surface; ships with localhost defaults in data/loominum/config.json (port 7773, TLS off).
  • src/loominum/README.md — the API documentation (server/client/browser).
  • src/loominum/EVENTS.md — event-system documentation.
  • src/loominum/NGINX.md — deployment notes for fronting the server with nginx (TLS termination, path-based routing).
  • CDP sidecar — implemented in src/loominum/cdp.py; run via the lum-cdp console script. Bridge logic covered by an automated fake-CDP test harness in tests/test_cdp.py.

Layout

loominum/
├── README.md              this file
├── HANDOFF.md             design doc for the next agent picking this up
├── src/loominum/        library source (JS-injection base + CDP sidecar)
│   ├── __init__.py
│   ├── server.py          WS server — handles both the /remote browser and /client python endpoints
│   ├── client.py          Python client
│   ├── config.py          config schema + discovery (discover_config, LumConf.auto)
│   ├── cdp.py             CDP sidecar transport (lum-cdp)
│   ├── htdocs/            served static files: remote.js (the bootstrap),
│   │                       evtcap.js (console tap helper), install-cert scripts
│   ├── scripts/           cert install helpers
│   ├── README.md          API reference
│   ├── EVENTS.md          event system
│   └── NGINX.md           nginx deployment notes
├── data/loominum/
│   └── config.json        template — localhost defaults, no TLS
└── tests/
    ├── test_cdp.py        CDP bridge tests (fake-CDP harness)
    ├── test_config.py     config discovery + env-override tests
    └── test_lum.py        manual live-server smoke script

Installation

pip install loominum

Installs the lum (server) and lum-cdp (CDP sidecar) console scripts.

Configuration

Loominum runs with localhost defaults and no config file required. To customize, drop a config.json in any conventional location or override single settings via environment variables — full precedence rules in src/loominum/README.md.

{
  "verbose": false,
  "log_file": "log/lum.log",
  "server_url": "http://127.0.0.1:7773",
  "client_url": "http://127.0.0.1:7773",
  "cert_sans": null
}

Quick paths:

  • A file: ./loominum.json, ~/.config/loominum/config.json, or $LOOMINUM_CONFIG=/full/path.json. (PRJ_DIR is still honored for back-compat but no longer required.)
  • A single setting: LOOMINUM_SERVER_URL, LOOMINUM_CLIENT_URL, LOOMINUM_LOG_FILE, LOOMINUM_CERT_SANS, LOOMINUM_VERBOSE.

For TLS: set cert_sans to a comma-separated list of hostnames/IPs to include in the cert SANs (e.g. "localhost,192.168.1.100") and use an https:// scheme on server_url. Cert install helpers under src/loominum/scripts/.

Quick start (current JS-injection mode)

lum    # or, from a source checkout: PYTHONPATH=src python -m loominum.server

Then in the browser DevTools console of the target page:

fetch('http://127.0.0.1:7773/remote.js?t='+Date.now()).then(r=>r.text()).then(eval);

Then from Python:

import asyncio
from loominum import LumClient

async def main():
    async with LumClient() as client:
        title = await client.exec('document.title')
        print(title)

asyncio.run(main())

See src/loominum/README.md for the full API.

Quick start (CDP sidecar mode)

Launch a Chromium-based browser with remote debugging enabled:

chromium --remote-debugging-port=9222

Then start the server and the sidecar (it discovers the target tab, auto-injects the page bridge, and impersonates a browser to the server):

lum &                       # start the server (installed console script)
lum-cdp --target-url example.com

From Python, the API is identical to JS-injection mode:

import asyncio
from loominum import LumClient

async def main():
    async with LumClient() as client:
        print(await client.exec('document.title'))

asyncio.run(main())

The CDP transport survives page navigations (init code re-runs on every new document) and can dispatch trusted input via CDPTransport.dispatch_key, type_text, and click.

Testing

pytest tests/test_cdp.py

Covers the bridge with a fake CDP browser (no real Chrome required). A real- browser scenario auto-runs when localhost:9222 is reachable and otherwise skips.

License

Apache-2.0 — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

loominum-0.2.0.tar.gz (62.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

loominum-0.2.0-py3-none-any.whl (59.7 kB view details)

Uploaded Python 3

File details

Details for the file loominum-0.2.0.tar.gz.

File metadata

  • Download URL: loominum-0.2.0.tar.gz
  • Upload date:
  • Size: 62.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for loominum-0.2.0.tar.gz
Algorithm Hash digest
SHA256 29daec7aa354b48234d23681f0a9cdd5313f944bb91de243086131075ae4aeb2
MD5 8ee83c6981168f1d0ee68c898f109a92
BLAKE2b-256 6402bd8d6eafddc7cbab51199ab593270f50dad06a9e58c5d24ae33fa72d474a

See more details on using hashes here.

Provenance

The following attestation bundles were made for loominum-0.2.0.tar.gz:

Publisher: workflow.yml on apresence/loominum

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file loominum-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: loominum-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 59.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for loominum-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ee2e59a96adcc9aa91fcfb0b393e090e4cc44fb73caba308bcee81432f58f159
MD5 525b3bbd5134fec512644af225a1e069
BLAKE2b-256 5daba7b967f77202a307e914ef0d40ede1d2d94046fc195ba4d50fa27a094318

See more details on using hashes here.

Provenance

The following attestation bundles were made for loominum-0.2.0-py3-none-any.whl:

Publisher: workflow.yml on apresence/loominum

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page