When multiple team members or services use CaptchaAI, you need key management, usage tracking, and spending controls. Here's how to set it up.
Team Usage Patterns
| Pattern | When to Use |
|---|---|
| Single shared key | Small team, simple tracking |
| Key per user | Per-user spending limits and audit |
| Key per project | Cost allocation by project |
| Key per environment | Dev/staging/prod isolation |
Team Key Manager
import os
import json
import time
import threading
from collections import defaultdict
class TeamKeyManager:
"""Manage multiple API keys with per-user tracking."""
def __init__(self, config_path=None):
self._keys = {}
self._usage = defaultdict(lambda: {
"solves": 0, "cost": 0.0,
"daily_solves": 0, "daily_reset": time.time(),
})
self._lock = threading.Lock()
if config_path:
self._load_config(config_path)
def add_user(self, user_id, api_key, daily_limit=500):
"""Register a user with their API key and limits."""
self._keys[user_id] = {
"key": api_key,
"daily_limit": daily_limit,
"active": True,
}
def get_key(self, user_id):
"""Get API key for a user, enforcing limits."""
with self._lock:
if user_id not in self._keys:
raise ValueError(f"User {user_id} not registered")
user = self._keys[user_id]
if not user["active"]:
raise PermissionError(f"User {user_id} is deactivated")
usage = self._usage[user_id]
# Reset daily counter
if time.time() - usage["daily_reset"] > 86400:
usage["daily_solves"] = 0
usage["daily_reset"] = time.time()
# Check daily limit
if usage["daily_solves"] >= user["daily_limit"]:
raise QuotaExceeded(
f"User {user_id} daily limit reached ({user['daily_limit']})"
)
return user["key"]
def record_solve(self, user_id, cost=0.003):
"""Record a successful solve for a user."""
with self._lock:
self._usage[user_id]["solves"] += 1
self._usage[user_id]["cost"] += cost
self._usage[user_id]["daily_solves"] += 1
def get_user_stats(self, user_id):
"""Get usage statistics for a user."""
with self._lock:
return dict(self._usage[user_id])
def get_team_report(self):
"""Get usage report for all users."""
with self._lock:
report = {}
for user_id, usage in self._usage.items():
report[user_id] = {
"total_solves": usage["solves"],
"total_cost": f"${usage['cost']:.4f}",
"daily_solves": usage["daily_solves"],
"daily_limit": self._keys.get(user_id, {}).get("daily_limit", "N/A"),
}
return report
def deactivate_user(self, user_id):
"""Disable a user's access."""
if user_id in self._keys:
self._keys[user_id]["active"] = False
def _load_config(self, config_path):
"""Load team config from file."""
with open(config_path, "r") as f:
config = json.load(f)
for user in config.get("users", []):
self.add_user(
user["id"],
user["api_key"],
user.get("daily_limit", 500),
)
class QuotaExceeded(Exception):
pass
Usage with Team Manager
import requests
import time
class TeamSolver:
"""CAPTCHA solver with team key management."""
def __init__(self, key_manager):
self.keys = key_manager
def solve(self, user_id, params):
"""Solve CAPTCHA on behalf of a user."""
api_key = self.keys.get_key(user_id) # Checks limits
data = {"key": api_key, "json": 1, **params}
resp = requests.post(
"https://ocr.captchaai.com/in.php", data=data, timeout=30,
)
result = resp.json()
if result.get("status") != 1:
raise RuntimeError(result.get("request"))
task_id = result["request"]
time.sleep(10)
for _ in range(24):
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": api_key, "action": "get",
"id": task_id, "json": 1,
}, timeout=15)
data = resp.json()
if data.get("status") == 1:
self.keys.record_solve(user_id)
return data["request"]
if data["request"] != "CAPCHA_NOT_READY":
raise RuntimeError(data["request"])
time.sleep(5)
raise TimeoutError("Solve timeout")
# Setup
manager = TeamKeyManager()
manager.add_user("alice", os.environ["CAPTCHAAI_KEY_ALICE"], daily_limit=1000)
manager.add_user("bob", os.environ["CAPTCHAAI_KEY_BOB"], daily_limit=500)
manager.add_user("ci_pipeline", os.environ["CAPTCHAAI_KEY_CI"], daily_limit=200)
solver = TeamSolver(manager)
# Each user solves with their own limits
token = solver.solve("alice", {
"method": "userrecaptcha",
"googlekey": "SITEKEY",
"pageurl": "https://example.com",
})
Configuration File Format
{
"users": [
{
"id": "alice",
"api_key": "ENV:CAPTCHAAI_KEY_ALICE",
"daily_limit": 1000,
"role": "admin"
},
{
"id": "bob",
"api_key": "ENV:CAPTCHAAI_KEY_BOB",
"daily_limit": 500,
"role": "user"
},
{
"id": "ci_pipeline",
"api_key": "ENV:CAPTCHAAI_KEY_CI",
"daily_limit": 200,
"role": "service"
}
]
}
Note: Use environment variable references (e.g.,
ENV:VARIABLE_NAME) instead of hardcoding keys in config files.
Team Reporting
def print_team_report(manager):
"""Print formatted team usage report."""
report = manager.get_team_report()
print(f"{'User':<20} {'Solves':>8} {'Cost':>10} {'Daily':>8} {'Limit':>8}")
print("-" * 60)
total_solves = 0
total_cost = 0.0
for user_id, stats in report.items():
solves = stats["total_solves"]
cost = float(stats["total_cost"].replace("$", ""))
daily = stats["daily_solves"]
limit = stats["daily_limit"]
print(f"{user_id:<20} {solves:>8} ${cost:>9.4f} {daily:>8} {limit:>8}")
total_solves += solves
total_cost += cost
print("-" * 60)
print(f"{'TOTAL':<20} {total_solves:>8} ${total_cost:>9.4f}")
FAQ
Should each team member have their own CaptchaAI account?
For teams under 5, a shared account with usage tracking works. For larger teams, separate accounts provide better billing isolation and individual API keys.
How do I prevent one team member from overspending?
Set daily limits per user via the TeamKeyManager. When a user hits their limit, the system blocks additional solves until the next day.
Can I track which project each solve belongs to?
Yes. Add a project_id parameter to the record_solve method and include it in your audit logs for per-project cost allocation.
Related Guides
Scale CaptchaAI across your team — get started.
Discussions (0)
Join the conversation
Sign in to share your opinion.
Sign InNo comments yet.