Based on the original open-source project
ismoiloffS/EzSolver by Ismoiloff
License: MIT (see LICENSE)
This repository keeps the original simple launch path that already works for most users, and only adds a few practical production fixes.
HTTP API is fully compatible with upstream EzSolver.
| Original | This fork | |
|---|---|---|
| Author / base | ismoiloffS/EzSolver | same solve flow |
| Launch | uc.start(browser_executable_path, headless=False, user_data_dir=...) |
same + sandbox=False default |
| API | POST /solve |
unchanged |
What we did not change
POST /solverequest/response JSON- success:
{"token": "...", "elapsed": 4.23} - error:
{"error": "..."}with HTTP 500 - CLI client usage
Minimal hardening (only when needed)
- Default
EZ_NO_SANDBOX=1→sandbox=False(root/docker/www) - Writable profile fallback if
/tmp/ts_profileis owned by another user - Service binds
0.0.0.0, defaultMAX_WORKERS=2 - Default unique profile per solve + short start gap (reduces concurrent first-fail)
- Python 3.8+
- Google Chrome / Chromium
pip install nodriver- Linux headless:
sudo apt install xvfb
git clone https://github.com/50521136/EzSolver.git
cd EzSolver
pip install nodriver
# Linux:
sudo apt install -y xvfb google-chrome-stableDefaults are already baked into service.py. No export required:
python service.pyEquivalent built-in defaults:
EZ_NO_SANDBOX=1MAX_WORKERS=2- unique profile on
- try raise open-files soft limit to
65535 - bind
0.0.0.0:8191
Optional CLI overrides:
python service.py --workers 2 --port 8191
python service.py --workers 1
python service.py --sandbox # only if you really need sandbox on
python service.py --shared-profile # original shared profile mode
python service.py --nofile 65535 # default; use --nofile 0 to skipEnv vars still work if your panel/process manager sets them.
Service listens on http://0.0.0.0:8191.
Solve
curl -s -X POST http://127.0.0.1:8191/solve \
-H "Content-Type: application/json" \
-d '{"sitekey":"0x4AAAA...","siteurl":"https://example.com/","timeout":45}'Success:
{"token":"0....","elapsed":12.34}Failure:
{"error":"..."}Health
curl -s http://127.0.0.1:8191/healthpython clientsend.py <sitekey> <siteurl> [timeout]| Variable | Default | Meaning |
|---|---|---|
PORT |
8191 |
HTTP port |
MAX_WORKERS |
2 |
concurrent Chrome workers |
EZ_NO_SANDBOX |
1 |
pass sandbox=False to nodriver |
TS_PROFILE_DIR |
/tmp/ts_profile (Linux) |
profile directory |
CHROME_PATH |
auto-detect | Chrome/Chromium binary |
EZ_UNIQUE_PROFILE |
1 |
unique profile per solve (set 0 for shared) |
EZ_START_GAP |
1.0 |
min seconds between Chrome launches |
EZ_KEEP_PROFILE |
0 |
keep unique profiles if 1 |
Pull latest and run the same way you ran original:
git pull
export EZ_NO_SANDBOX=1
python service.pyIf you still see Permission denied: /tmp/ts_profile:
sudo rm -rf /tmp/ts_profile
export TS_PROFILE_DIR=$HOME/.cache/ezsolver/ts_profile
mkdir -p "$TS_PROFILE_DIR"
python service.pyIf you still see Failed to connect to browser:
sudo apt install -y xvfb google-chrome-stable
export CHROME_PATH=/usr/bin/google-chrome-stable
python service.pyOriginal project by Ismoiloff: ismoiloffS/EzSolver
Each solve now:
browser.stop()- hard-kills leftover Chrome for that profile
- deletes unique profile dirs (
w_*)
Service also runs a background janitor every EZ_JANITOR_SEC (default 120s).
Manual cleanup if needed:
pkill -f "chrome.*ts_profile" || true
rm -rf /tmp/ts_profile/w_* 2>/dev/null || true
ulimit -n 65535If you see Too many open files, restart service with MAX_WORKERS=1 and raise ulimit -n.