Spaces:
Paused
title: Playwright
emoji: π₯
colorFrom: green
colorTo: yellow
sdk: docker
app_port: 7860
pinned: false
Playwright API
Public Playwright execution API. POST /run with JSON body:
{ "code": "const { chromium } = require('playwright'); ..." }
Code may use either CommonJS (require) or ESM (import).
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | / |
HTML landing page |
| GET | /api/info |
service info as JSON |
| GET | /health |
liveness probe |
| POST | /run |
execute Playwright code |
Helpers in user code
const playwright = require('playwright');
const stealth = require('stealth'); // anti-bot launch wrapper
const captcha = require('captcha'); // local CAPTCHA solvers + solver client
The bundled CAPTCHA suite β no third-party APIs, no per-solve fees:
- Turnstile / "Just a moment" β
captcha.solveTurnstile(page)andcaptcha.clearChallenge(siteurl)use the bundled solver service (Camoufox, runs in the same container). - reCAPTCHA v2 β
captcha.solveRecaptchaV2(page)does the audio fallback flow with local Whisper. - Text/image CAPTCHA β
captcha.ocrBuffer(buf)via local Tesseract. - Math CAPTCHA β
captcha.solveMath('2 + 3 * 4'). - Cookie jar β
captcha.saveCookies / loadCookiesto skip re-solving challenges on subsequent requests.
Deploy
Hugging Face Space
Push to git@hf.co:spaces/<user>/<name>. The Dockerfile bundles both the
Playwright API and the Turnstile solver in a single image (HF only allocates
one container per Space). A supervisor script starts the solver in the
background and the API in the foreground.
VPS / your own server
git clone https://github.com/cv3inx/playwright.git
cd playwright
cp .env.example .env
docker compose up -d --build
Compose runs two containers on an internal Docker network:
playwright-api(port 7860 β host) β the APIturnstile-solver(port 9988, internal only) β the solver
Wired automatically β playwright-api calls http://turnstile-solver:9988
inside the network. No external URLs, no API keys.
For HTTPS, put nginx/caddy/traefik in front of port 7860.
Hardening
Each request runs in an isolated process tree under a per-request workspace
(/tmp/run-<id>) with strict ulimits, stripped env, and setpriv --no-new-privs.
On completion (success, error, or timeout), the entire process group is
SIGKILL'd, the session is wiped (pkill -s), the workspace is rm -rf'd, and
orphaned chromium SHM segments are cleaned up β preventing any binary the
script wrote from persisting between requests.
Concurrent requests are isolated from each other: each gets its own pgid, session, and workspace, so one request's burn cannot disrupt another in flight.