Fetching rendered DOM easily and simply. Like cURL.
Using Headless Chromium.
The repository tracks TODO and @ts-expect-error markers with gh-counter.
It also tracks built dist/ artifact size with gh-build-size.
So this library provides simplicity in these cases:
- Crawlers
- Text browsers
- Command line interface like curl wget
published on npm
$ npm install rendering-proxy$ yarn add rendering-proxy$ bun add rendering-proxy$ rendering-proxy --help
rendering-proxy <command>
Commands:
rendering-proxy cli [url] CLi mode
rendering-proxy server Server mode
Options:
--version Show version number [boolean]
--help Show help [boolean]$ yarn run rendering-proxy cli https://example.com/
<html><head>
...
</body></html>$ yarn run rendering-proxy server --port=8080$ curl http://localhost:8080/https://example.com/
<html><head>
...
</body></html>When -e, --evaluate is specified, JavaScript code is evaluated before getting DOM.
$ yarn run rendering-proxy cli https://example.com/ -e 'document.title = "updated"' -e 'document.title += " twice"'
<!DOCTYPE html><html><head>
<title>updated twice</title>
...Send the options via request header X-Rendering-Proxy (case-insensitive).
Receive the results via response header X-Rendering-Proxy (case-insensitive).
curl -H 'X-Rendering-Proxy: {"evaluates": ["1 + 1"], "waitUntil": "load"}' --include http://localhost:8080/https://example.com/
HTTP/1.1 200 OK
...
x-rendering-proxy: [{"success":true,"result":2,"script":"1 + 1"}]
x-rendering-proxy-version: 1
...
<!DOCTYPE html><html><head>
<title>Example Domain</title>Request header X-Rendering-Proxy — JSON object:
| field | type | default | description |
|---|---|---|---|
waitUntil |
"load" | "domcontentloaded" | "networkidle" | "commit" |
"load" |
Playwright lifecycle event to wait for. Unknown values fall back to "load" with a server-side warning. |
evaluates |
string[] |
[] |
JavaScript snippets to evaluate before capturing the DOM. |
timeout |
number (ms) |
none | Navigation timeout in milliseconds. |
Response header X-Rendering-Proxy — JSON array of EvaluateResult:
type EvaluateResult =
| { success: true; script: string; result: unknown }
| { success: false; script: string; result: string }Response header X-Rendering-Proxy-Version — integer string (e.g. "1").
Clients can use this to detect schema changes across server upgrades.
Install lefthook and register the Git hooks:
lefthook installThis sets up two hooks that mirror what CI runs:
- pre-commit: runs
bun run lintandbun run typecheckon every commit. - pre-push: runs
bun run lint,bun run typecheck, andbun run testbefore each push.
CI still runs the full suite on every pull request and push to main — the hooks bring that feedback earlier, to your local machine.
rendering-proxy exports two namespaces for programmatic use:
import { server, cli } from 'rendering-proxy'Starts the rendering proxy HTTP server. Exits when the process receives SIGTERM or SIGINT.
import { server } from 'rendering-proxy'
await server.main({ port: 8080, name: 'chromium', headless: true })Options:
| Option | Type | Default | Description |
|---|---|---|---|
port |
number |
8080 |
Port to listen on |
name |
'chromium' | 'firefox' | 'webkit' |
'chromium' |
Browser engine |
headless |
boolean |
true |
Run browser in headless mode |
Creates an http.Server backed by a pre-launched Playwright Browser instance.
import { chromium } from 'playwright'
import { server } from 'rendering-proxy'
const browser = await chromium.launch()
const httpServer = await server.createServer({ browser, port: 8080 })
// Use httpServer.close() to stopReturns a (req, res) => void handler suitable for use with an existing http.Server.
import http from 'node:http'
import { chromium } from 'playwright'
import { server } from 'rendering-proxy'
const browser = await chromium.launch()
const httpServer = http.createServer(server.createHandler(browser))
httpServer.listen(8080)Renders a URL and writes the resulting HTML to any Writable stream.
import { cli } from 'rendering-proxy'
await cli.renderToStream(
{
url: 'https://example.com',
name: 'chromium',
waitUntil: 'networkidle',
evaluates: ['document.title = "patched"'],
},
process.stdout,
)Renders a URL and writes to process.stdout. Equivalent to the CLI command.
import { cli } from 'rendering-proxy'
await cli.main({ url: 'https://example.com', name: 'chromium' })The 3-Clause BSD License. See also LICENSE file.
