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.1.0.tar.gz (50.6 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.1.0-py3-none-any.whl (56.6 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for loominum-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d6b5868fbe23abe4ab1655627a0920f7263274ee76835199e1749c11a5c83abc
MD5 88c32c34d3baf434e5d19ed4b916b7c6
BLAKE2b-256 5761433357dffa9c3f841008d7ca1328d692e70ab73cf2f78d0b700f8ced3845

See more details on using hashes here.

Provenance

The following attestation bundles were made for loominum-0.1.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.1.0-py3-none-any.whl.

File metadata

  • Download URL: loominum-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 56.6 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.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5883c391be09d95c47ffc6734830182ef1ec7b5f6a21891e13ba35d1a091a619
MD5 60af9c9425f7b73de44c00fec4902252
BLAKE2b-256 e4055f76f20ecd2948397c88814b371a749e78ca1fbee03e27db76bb0d8330fe

See more details on using hashes here.

Provenance

The following attestation bundles were made for loominum-0.1.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