playwright / README.md
cv3inx's picture
Bundle turnstile-solver in the project (no external URL needed)
f26e640
|
Raw
History Blame Contribute Delete
2.98 kB
---
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.