Spaces:
Paused
Paused
File size: 2,981 Bytes
2e38705 69f12cd 2e38705 69f12cd 579a226 f26e640 579a226 f26e640 579a226 f26e640 579a226 f26e640 579a226 f26e640 579a226 69f12cd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | ---
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:
```json
{ "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
```js
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)` and
`captcha.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 / loadCookies` to 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
```sh
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 API
- `turnstile-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.
|