Der CaptchaAI-API-Schlüssel gehört in eine Umgebungsvariable – lokal in eine .env-Datei außerhalb der Versionskontrolle, im Betrieb in die Secret-Verwaltung der Plattform. Ein Schlüssel im Quellcode ist kein Konfigurationsdetail, sondern ein Vorfall mit Vorlaufzeit.
Das Muster kennt fast jedes Team: Ein Scraper läuft seit Monaten auf einem VPS bei Hetzner, das Repository wird für einen Freelancer-Auftrag öffentlich gestellt – und der Schlüssel aus Zeile 12 von solver.py gleich mit.
Vier Ebenen kommen in Frage: .env lokal, Systemvariablen auf dem Server, Docker Secrets im Container, maskierte Variablen in der CI. Dazu ein Startup-Check, der einen ungültigen Schlüssel meldet, bevor die erste Anfrage an in.php rausgeht.
Wo der API-Schlüssel je nach Umgebung liegen sollte
| Umgebung | Ablage | Absicherung |
|---|---|---|
| Lokale Entwicklung | .env im Projektstamm |
Eintrag in .gitignore |
| Server / VPS | EnvironmentFile der systemd-Unit |
chmod 600, Service-Benutzer |
| Container | Docker Secret | kein Schlüssel im Image |
| CI/CD | maskierte Variable | keine Ausgabe im Job-Log |
| Mehrere Teams | Cloud Secret Manager | Rotation, Zugriffsprotokoll |
Die Faustregel: Je mehr Personen Zugriff haben, desto weiter muss der Schlüssel vom Code wegwandern.
Hinweis: Art. 32 DSGVO verlangt angemessene technische Maßnahmen für Systeme, die personenbezogene Daten verarbeiten. Ein API-Schlüssel im Git-Verlauf jedes ehemaligen Projektbeteiligten ist schwer zu begründen.
.env-Datei für die lokale Entwicklung
Legen Sie im Projektstammverzeichnis eine .env-Datei an:
CAPTCHAAI_API_KEY=your_actual_api_key_here
Der Eintrag in .gitignore folgt sofort danach, nicht später:
# .gitignore
.env
.env.local
.env.production
Wichtig:
.gitignorewirkt nur auf Dateien, die Git noch nicht verfolgt. Wurde die.envschon einmal committet, greift der Eintrag nicht mehr – dann hilft der Notfallplan weiter unten.
Ins Repository gehört stattdessen eine .env.example mit leeren Werten – als Referenz für neue Teammitglieder.
Python mit python-dotenv
pip install python-dotenv
import os
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
# Use in API calls
import requests
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": "6Le-SITEKEY",
"pageurl": "https://example.com",
"json": "1",
})
print(resp.json())
Zwei Details ersparen später Fehlersuche:
- Der Zugriff über eckige Klammern bricht sofort ab, wenn die Variable fehlt;
os.environ.get()liefert stattdessenNone– der Fehler fällt später auf. - Ein leerer Schlüssel endet in
ERROR_WRONG_USER_KEY– der Fehler steckt dann in der Konfiguration.
Node.js mit dotenv
npm install dotenv
require('dotenv').config();
const API_KEY = process.env.CAPTCHAAI_API_KEY;
if (!API_KEY) {
console.error('CAPTCHAAI_API_KEY not set');
process.exit(1);
}
// Use in API calls
const axios = require('axios');
const resp = await axios.post('https://ocr.captchaai.com/in.php', null, {
params: {
key: API_KEY,
method: 'userrecaptcha',
googlekey: '6Le-SITEKEY',
pageurl: 'https://example.com',
json: 1,
},
});
console.log(resp.data);
Dasselbe Prinzip in Node.js, mit zwei Stolpersteinen:
require('dotenv').config()muss vor jedem Modul stehen, das den Schlüssel beim Import liest.- Ohne
process.exit(1)läuft der Worker mit leerem Schlüssel weiter.
Umgebungsvariablen auf Betriebssystemebene
Sobald der Code den Entwicklungsrechner verlässt, ist die .env-Datei nicht mehr die naheliegende Ablage: Auf einem Server mit einem einzigen Dienst gehört der Wert in die Prozessumgebung.
Linux und macOS
export CAPTCHAAI_API_KEY="your_actual_api_key_here"
# Persist across sessions — add to ~/.bashrc or ~/.zshrc
echo 'export CAPTCHAAI_API_KEY="your_actual_api_key_here"' >> ~/.bashrc
Das Shell-Profil gilt aber nur für interaktive Sitzungen. Für Dienste auf einem Server bei Hetzner, IONOS oder netcup ist die systemd-Unit der bessere Ort:
EnvironmentFile=/etc/captchaai.envin der Unit eintragen.- Die Datei bekommt
chmod 600und den Service-Benutzer als Besitzer. - Kein anderes Konto auf dem System liest den Wert mit.
Windows und PowerShell
$env:CAPTCHAAI_API_KEY = "your_actual_api_key_here"
# Persist permanently
[System.Environment]::SetEnvironmentVariable("CAPTCHAAI_API_KEY", "your_actual_api_key_here", "User")
Die erste Zeile gilt nur für die laufende Sitzung, die zweite schreibt den Wert ins Benutzerprofil. Läuft die Automatisierung als Windows-Dienst unter einem eigenen Konto, setzen Sie die Variable im Kontext dieses Kontos – sonst startet der Dienst ohne Schlüssel.
Container: Docker, Compose und Docker Secrets
Schlüssel an docker run übergeben
docker run -e CAPTCHAAI_API_KEY="your_key" my-scraper
Für einen Test in Ordnung, für den Dauerbetrieb nicht: Der Wert landet in der Shell-History und ist über docker inspect lesbar.
Docker Compose
# docker-compose.yml
services:
scraper:
image: my-scraper
environment:
- CAPTCHAAI_API_KEY=${CAPTCHAAI_API_KEY}
${CAPTCHAAI_API_KEY} verweist auf die Umgebungsvariable des Hosts – der Schlüssel steht weder in der Compose-Datei noch im Image.
Docker Secrets im Swarm-Betrieb
echo "your_actual_api_key_here" | docker secret create captchaai_key -
# docker-compose.yml (Swarm mode)
services:
scraper:
image: my-scraper
secrets:
- captchaai_key
secrets:
captchaai_key:
external: true
Im Code lesen Sie den Wert aus dem eingehängten Pfad:
with open("/run/secrets/captchaai_key") as f:
API_KEY = f.read().strip()
Hinweis: Secrets liegen im Container ausschließlich unter
/run/secrets/. Sie erscheinen weder indocker inspectnoch in einem versehentlich ausgegebenen Environment-Dump – das ist der Vorteil gegenüber der Umgebungsvariable.
CI/CD: maskierte Variablen statt Klartext
GitHub Actions
# .github/workflows/scrape.yml
jobs:
scrape:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: python scraper.py
env:
CAPTCHAAI_API_KEY: ${{ secrets.CAPTCHAAI_API_KEY }}
Hinterlegen Sie den Schlüssel unter Settings → Secrets and variables → Actions → New repository secret.
Hinweis: Die Maskierung greift nur bei exakten Treffern im Log. Sobald ein Skript den Schlüssel zerlegt oder kodiert, ist der Schutz weg – behandeln Sie Logs grundsätzlich als lesbar.
GitLab CI
# .gitlab-ci.yml
scrape:
script:
- python scraper.py
variables:
CAPTCHAAI_API_KEY: $CAPTCHAAI_API_KEY
In vielen deutschen Unternehmen läuft die Pipeline auf einer selbst gehosteten GitLab-Instanz. Die Variable legen Sie unter Settings → CI/CD → Variables an:
- „Masked“ verhindert die Ausgabe im Job-Log; der Wert braucht dafür eine Mindestlänge und keine Zeilenumbrüche.
- „Protected“ beschränkt Produktions-Schlüssel auf geschützte Branches.
API-Schlüssel beim Start validieren
Ein fehlender Schlüssel soll den Prozess sofort beenden – nicht nach 200 halb abgearbeiteten Aufgaben:
import os
import sys
import requests
API_KEY = os.environ.get("CAPTCHAAI_API_KEY")
if not API_KEY:
print("ERROR: CAPTCHAAI_API_KEY environment variable not set")
sys.exit(1)
# Verify key works
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "getbalance", "json": "1"
}).json()
if resp["status"] != 1:
print(f"ERROR: Invalid API key — {resp['request']}")
sys.exit(1)
print(f"API key valid — balance: ${float(resp['request']):.2f}")
res.php mit action=getbalance beantwortet zwei Fragen auf einmal: Existiert der Schlüssel, und ist Guthaben vorhanden? ERROR_KEY_DOES_NOT_EXIST deutet auf einen Tippfehler oder eine nicht geladene .env-Datei hin.
Häufige Fehler und die bessere Praxis
| Fehler | Risiko | Besser |
|---|---|---|
.env eingecheckt |
bleibt im Repo-Verlauf | vorher in .gitignore eintragen |
| Schlüssel geloggt | landet im Log-Aggregator | nur letzte Zeichen loggen |
| Hardcodierung im Dockerfile | in der Image-Ebene eingebrannt | ENV zur Laufzeit setzen |
| Weitergabe per Chat | bleibt in fremden Verläufen | Secret-Manager nutzen |
| Ein Schlüssel überall | Leak in Staging trifft Produktion | getrennte Schlüssel je Umgebung |
Notfallplan: Der Schlüssel liegt bereits im Repository
Das Löschen der Datei hilft nicht – der alte Stand bleibt im Verlauf lesbar. Gehen Sie in dieser Reihenfolge vor:
- Schlüssel rotieren im CaptchaAI-Dashboard – der alte Wert verliert damit seinen Nutzen.
- Neuen Wert ausrollen: Server, Container, CI-Variablen, Entwicklungsrechner.
- Guthaben und Statistik prüfen – auf Aufgaben, die Sie nicht ausgelöst haben.
- Git-Verlauf bereinigen als Aufräumarbeit, nicht als Sicherheitsmaßnahme.
- Secret-Scan ergänzen, damit derselbe Fehler vor dem Push auffällt.
Mehrere Schlüssel und Umgebungen sauber trennen
Ein Schlüssel je Umgebung ist der Normalfall: Staging und Produktion sollten sich unabhängig rotieren lassen. Mehrere Werte legen Sie als kommaseparierte Liste ab:
CAPTCHAAI_KEYS=key1,key2,key3
keys = os.environ["CAPTCHAAI_KEYS"].split(",")
Am Durchsatz ändert das nichts: CaptchaAI rechnet pro gleichzeitigem Thread ab, nicht pro Schlüssel. Wer mehr parallele Abfragen braucht, wählt den passenden Plan – BASIC ab 15 $/Monat mit 5 Threads, STANDARD 30 $ mit 15 Threads.
FAQ
Reicht eine .env-Datei auch auf dem Produktionsserver?
Für einen einzelnen Dienst ja – sofern die Datei außerhalb des Webroots liegt, 600-Rechte hat und dem Service-Benutzer gehört. Bei mehreren Anwendungen oder Teams ist ein Secret-Manager (Azure Key Vault, HashiCorp Vault) tragfähiger.
Wie halte ich den Schlüssel aus Logs und Fehlerberichten heraus?
Protokollieren Sie ihn nie vollständig. Zwei Stellen werden oft übersehen:
- Exception-Tracker, die im Fehlerfall die Prozessumgebung mitschicken.
- Debug-Ausgaben von HTTP-Bibliotheken, die die Anfrage an
in.phpsamtkey-Parameter mitschreiben.
Warum findet mein Container die Umgebungsvariable nicht?
Fast immer, weil sie im falschen Kontext gesetzt wurde. Eine Variable in der Shell des Hosts wird nicht automatisch weitergereicht – sie muss über -e, env_file oder environment übergeben werden.
Brauche ich für jeden CAPTCHA-Typ einen eigenen Schlüssel?
Nein. Derselbe Schlüssel adressiert alle unterstützten Methoden – reCAPTCHA v2 und v3, Cloudflare Turnstile, GeeTest v3 sowie Bild- und Rasterbild-CAPTCHAs. Er ist an Ihr Konto gebunden, nicht an einen CAPTCHA-Typ.
Schützen Sie Ihre CaptchaAI-Integration ab dem ersten Commit
Holen Sie sich Ihren API-Schlüssel auf captchaai.com und hinterlegen Sie ihn gleich als Umgebungsvariable – das erspart Ihnen die Rotation unter Zeitdruck.