Loading...
Loading...
Auto batch-register Tavily API keys via browser automation and pool them behind a unified proxy gateway with web console
npx skill4agent add aradotso/trending-skills tavily-key-generator-proxySkill by ara.so — Daily 2026 Skills collection
| Component | Location | Purpose |
|---|---|---|
| Key Generator | root | Playwright-driven headless Firefox registers Tavily accounts, solves Turnstile CAPTCHAs, verifies email, extracts API key |
| API Proxy | | FastAPI service that round-robins requests across pooled keys, exposes |
git clone https://github.com/skernelx/tavily-key-generator.git
cd tavily-key-generator
pip install -r requirements.txt
playwright install firefox
cp config.example.py config.py
# Edit config.py with your CapSolver key and email backend
python main.pycd proxy/
cp .env.example .env
# Set ADMIN_PASSWORD in .env
docker compose up -d
# Console at http://localhost:9874/consoleconfig.py# CapSolver — recommended (~$0.001/solve, high success rate)
CAPTCHA_SOLVER = "capsolver"
CAPSOLVER_API_KEY = "CAP-..." # from capsolver.com
# Browser click fallback — free but low success rate
CAPTCHA_SOLVER = "browser"EMAIL_BACKEND = "cloudflare"
EMAIL_DOMAIN = "mail.yourdomain.com"
EMAIL_API_URL = "https://mail.yourdomain.com"
EMAIL_API_TOKEN = "your-worker-token"EMAIL_BACKEND = "duckmail"
DUCKMAIL_API_BASE = "https://api.duckmail.sbs"
DUCKMAIL_BEARER = "dk_..."
DUCKMAIL_DOMAIN = "duckmail.sbs"THREADS = 2 # Max 3 — more = higher ban risk
COOLDOWN_BASE = 45 # Seconds between registrations
COOLDOWN_JITTER = 15 # Random additional seconds
BATCH_LIMIT = 20 # Pause after this many registrationsPROXY_AUTO_UPLOAD = True
PROXY_URL = "http://localhost:9874"
PROXY_ADMIN_PASSWORD = "your-admin-password"python main.py
# Prompts: how many keys to generate, which email backend
# Output: api_keys.md with all generated keys
# If PROXY_AUTO_UPLOAD=True, keys are pushed to proxy automaticallyapi_keys.mdtvly-abc123...
tvly-def456...
tvly-ghi789...# Search — replace base URL only
curl -X POST http://your-server:9874/api/search \
-H "Authorization: Bearer tvly-YOUR_PROXY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query": "latest AI news", "search_depth": "basic"}'
# Extract
curl -X POST http://your-server:9874/api/extract \
-H "Authorization: Bearer tvly-YOUR_PROXY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"urls": ["https://example.com/article"]}'api_keyimport requests
response = requests.post(
"http://your-server:9874/api/search",
json={
"query": "Python web scraping",
"api_key": "tvly-YOUR_PROXY_TOKEN"
}
)
print(response.json())from tavily import TavilyClient
# Point SDK at your proxy — no other changes needed
client = TavilyClient(
api_key="tvly-YOUR_PROXY_TOKEN",
base_url="http://your-server:9874"
)
results = client.search("machine learning trends 2025")X-Admin-Password: your-password# List all keys
curl http://localhost:9874/api/keys \
-H "X-Admin-Password: secret"
# Add a single key
curl -X POST http://localhost:9874/api/keys \
-H "X-Admin-Password: secret" \
-H "Content-Type: application/json" \
-d '{"key": "tvly-abc123..."}'
# Bulk import from api_keys.md text
curl -X POST http://localhost:9874/api/keys \
-H "X-Admin-Password: secret" \
-H "Content-Type: application/json" \
-d '{"bulk": "tvly-abc...\ntvly-def...\ntvly-ghi..."}'
# Toggle key enabled/disabled
curl -X PUT http://localhost:9874/api/keys/{id}/toggle \
-H "X-Admin-Password: secret"
# Delete key
curl -X DELETE http://localhost:9874/api/keys/{id} \
-H "X-Admin-Password: secret"# Create access token
curl -X POST http://localhost:9874/api/tokens \
-H "X-Admin-Password: secret" \
-H "Content-Type: application/json" \
-d '{"label": "my-app"}'
# Returns: {"token": "tvly-...", "id": "..."}
# List tokens
curl http://localhost:9874/api/tokens \
-H "X-Admin-Password: secret"
# Delete token
curl -X DELETE http://localhost:9874/api/tokens/{id} \
-H "X-Admin-Password: secret"curl http://localhost:9874/api/stats \
-H "X-Admin-Password: secret"
# Returns: total_quota, used, remaining, active_keys, disabled_keyscurl -X PUT http://localhost:9874/api/password \
-H "X-Admin-Password: current-password" \
-H "Content-Type: application/json" \
-d '{"new_password": "new-secure-password"}'tvly-.envADMIN_PASSWORD=change-this-immediately
PORT=9874
# Optional: restrict CORS origins
CORS_ORIGINS=https://myapp.com,https://app2.comserver {
listen 443 ssl;
server_name tavily-proxy.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:9874;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}# replenish.py — run on cron when quota runs low
import requests
PROXY_URL = "http://localhost:9874"
ADMIN_PASSWORD = "your-password"
MIN_ACTIVE_KEYS = 10
def get_stats():
r = requests.get(f"{PROXY_URL}/api/stats",
headers={"X-Admin-Password": ADMIN_PASSWORD})
return r.json()
def trigger_registration(count: int):
"""Call your key generator as subprocess or import directly"""
import subprocess
subprocess.run(["python", "main.py", "--count", str(count)], check=True)
stats = get_stats()
active = stats["active_keys"]
if active < MIN_ACTIVE_KEYS:
needed = MIN_ACTIVE_KEYS - active
print(f"Pool low ({active} keys), registering {needed} more...")
trigger_registration(needed)| Problem | Cause | Fix |
|---|---|---|
| CAPTCHA solve failures | Tavily elevated bot detection | Pause several hours, reduce |
| Email verification timeout | Slow email delivery | Increase poll timeout in config |
| Keys immediately disabled in proxy | Tavily account flagged/suspended | Register from different IP |
| Missing system deps | Run |
| Docker compose port conflict | 9874 in use | Change |
| Wrong password | Check |
| IP ban during registration | Too many registrations | Use |
# Conservative — minimizes ban risk
THREADS = 1
COOLDOWN_BASE = 60
COOLDOWN_JITTER = 30
BATCH_LIMIT = 10ADMIN_PASSWORDconfig.py.gitignoreapi_keys.md