Eine Marktdaten-Pipeline läuft zuverlässig – bis auf einer Screener-Seite plötzlich ein reCAPTCHA oder eine Cloudflare-Turnstile-Abfrage auftaucht und der nächtliche Job leer zurückkommt. Die Lösung ist kein Reverse Engineering des Schutzes, sondern ein sauberer Zwischenschritt: Abfrage erkennen, Token über eine API lösen, mit dem Token erneut senden. Genau das übernimmt CaptchaAI programmgesteuert – für reCAPTCHA v2/v3, Cloudflare Turnstile und Cloudflare Challenge sowie Bild- und OCR-CAPTCHAs, wie sie auf Aktien-Screenern, SEC EDGAR und Marktdatenportalen vorkommen.
Dieser Leitfaden zeigt an lauffähigen Python-Beispielen, wie Sie CAPTCHAs an genau den Stellen abfangen, an denen sie einen Finanzdaten-Workflow unterbrechen: beim Screener-Scraping, beim Abruf von Pflichtveröffentlichungen und bei Turnstile-geschützten Marktdaten.
Warum Finanzportale den automatisierten Zugriff drosseln
Finanzseiten reagieren empfindlicher auf Bots als die meisten anderen Websites. Kursdaten, Screening-Ergebnisse und Pflichtveröffentlichungen sind wirtschaftlich wertvoll, und übermäßiger automatisierter Zugriff erzeugt echte Serverlast. Deshalb schalten Portale bei verdächtigen Mustern eine CAPTCHA-Abfrage vor – mal dauerhaft für jeden automatisierten Zugriff, mal erst, wenn das Anfragevolumen einen Schwellenwert überschreitet.
Welcher Typ auftaucht, hängt vom Portal ab. Die folgende Übersicht zeigt typische Quellen, den jeweils üblichen CAPTCHA-Typ und den Auslöser:
| Quelle | CAPTCHA-Typ | Auslöser | Datenwert |
|---|---|---|---|
| SEC EDGAR | reCAPTCHA v2 | Anfragen mit hohem Volumen | Unternehmensunterlagen |
| Yahoo Finance | reCAPTCHA v2 | Scraping-Erkennung | Kursdaten, Historie |
| Bloomberg | Cloudflare Turnstile | Jeder automatisierte Zugriff | Marktdaten |
| Finviz | reCAPTCHA v2 | Zugriff auf den Aktien-Screener | Screening-Ergebnisse |
| TradingView | Cloudflare Challenge | Rate-Limiting | Charts, Indikatoren |
| Morningstar | reCAPTCHA v3 | Datenexport-Seiten | Fondsanalysen |
Für DACH-Leser gilt: Das Muster ist dasselbe bei europäischen Quellen. Der Bundesanzeiger und das Unternehmensregister veröffentlichen Jahresabschlüsse öffentlich, drosseln Massenabrufe aber ebenfalls über Rate-Limiting und Abfragen. Die Vorgehensweise in diesem Artikel überträgt sich eins zu eins.
Aktien-Screener scrapen und CAPTCHAs abfangen
Der Kern jedes Workflows ist immer derselbe Zyklus:
- Seite abrufen und prüfen, ob statt der Daten eine CAPTCHA-Abfrage zurückkam.
- Das erkannte CAPTCHA über CaptchaAI lösen und das Token entgegennehmen.
- Die Anfrage mit dem Token in derselben Session wiederholen.
Die Funktion solve_captcha übermittelt die Aufgabe an in.php und fragt anschließend den Status an res.php ab, bis das Token bereitsteht.
import requests
import time
from bs4 import BeautifulSoup
import re
CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"
def solve_captcha(method, sitekey, pageurl, **kwargs):
data = {
"key": CAPTCHAAI_KEY,
"method": method,
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1,
}
data.update(kwargs)
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data=data)
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(5)
result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY, "action": "get",
"id": task_id, "json": 1,
})
r = result.json()
if r["request"] != "CAPCHA_NOT_READY":
return r["request"]
raise TimeoutError("Solve timeout")
class FinancialScraper:
def __init__(self, proxy=None):
self.session = requests.Session()
if proxy:
self.session.proxies = {"http": proxy, "https": proxy}
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
})
def scrape_screener(self, url):
"""Scrape stock screener, handling CAPTCHA if triggered."""
resp = self.session.get(url, timeout=30)
# Check for CAPTCHA
sitekey_match = re.search(r'data-sitekey="([^"]+)"', resp.text)
if sitekey_match:
sitekey = sitekey_match.group(1)
token = solve_captcha("userrecaptcha", sitekey, url)
# Resubmit with token
resp = self.session.post(url, data={
"g-recaptcha-response": token,
})
return self._parse_stocks(resp.text)
def _parse_stocks(self, html):
soup = BeautifulSoup(html, "html.parser")
stocks = []
for row in soup.select("table.screener-table tr")[1:]:
cols = row.select("td")
if len(cols) >= 8:
stocks.append({
"ticker": cols[1].get_text(strip=True),
"company": cols[2].get_text(strip=True),
"sector": cols[3].get_text(strip=True),
"price": cols[6].get_text(strip=True),
"change": cols[7].get_text(strip=True),
})
return stocks
# Usage
scraper = FinancialScraper(
proxy="http://user:pass@residential.proxy.com:5000"
)
stocks = scraper.scrape_screener("https://screener.example.com/screener.ashx?v=111")
for stock in stocks[:5]:
print(f"{stock['ticker']}: {stock['price']} ({stock['change']})")
Entscheidend ist, dass Sie das reCAPTCHA-Token über das Feld g-recaptcha-response an dieselbe Session zurückgeben, die die Seite geladen hat. So bleiben Cookies und Session-Kontext erhalten, und die Antwort enthält die Screening-Ergebnisse statt einer erneuten Abfrage.
Pflichtveröffentlichungen aus SEC EDGAR abrufen
SEC EDGAR kombiniert Rate-Limiting mit CAPTCHAs, sobald der Zugriff ein hohes Volumen erreicht. Zwei Details sind hier nicht optional: EDGAR verlangt einen aussagekräftigen User-Agent mit Kontakt-E-Mail, und bei einer 403-Antwort oder einer CAPTCHA-Seite muss der Abruf mit gelöstem Token wiederholt werden.
import json
class SECFilingScraper:
BASE_URL = "https://efts.sec.gov/LATEST"
def __init__(self, user_agent_email, proxy=None):
self.session = requests.Session()
if proxy:
self.session.proxies = {"http": proxy, "https": proxy}
# SEC requires identifying User-Agent
self.session.headers.update({
"User-Agent": f"CompanyName admin@{user_agent_email}",
"Accept": "application/json",
})
def search_filings(self, company, filing_type="10-K"):
"""Search EDGAR for specific filing types."""
url = f"{self.BASE_URL}/search-index"
params = {
"q": company,
"dateRange": "custom",
"forms": filing_type,
}
resp = self.session.get(url, params=params, timeout=30)
# Handle CAPTCHA if triggered
if "captcha" in resp.text.lower() or resp.status_code == 403:
sitekey = self._extract_sitekey(resp.text)
if sitekey:
token = solve_captcha("userrecaptcha", sitekey, url)
resp = self.session.post(url, data={
**params,
"g-recaptcha-response": token,
})
return resp.json() if resp.status_code == 200 else {}
def download_filing(self, filing_url):
"""Download individual filing document."""
resp = self.session.get(filing_url, timeout=60)
if resp.status_code == 200:
return resp.text
return None
def _extract_sitekey(self, html):
match = re.search(r'data-sitekey="([^"]+)"', html)
return match.group(1) if match else None
# Usage
sec = SECFilingScraper(
user_agent_email="example.com",
proxy="http://user:pass@proxy.example.com:5000",
)
filings = sec.search_filings("Apple Inc", "10-K")
Dasselbe Muster deckt europäische Register ab: Wer statt US-10-K-Filings deutsche Jahresabschlüsse aus dem Bundesanzeiger zieht, tauscht lediglich Basis-URL und Parser aus – die CAPTCHA- und Rate-Limiting-Logik bleibt identisch.
Turnstile-geschützte Marktdaten verarbeiten
Portale wie Bloomberg setzen auf Cloudflare Turnstile statt auf reCAPTCHA. Der Ablauf ändert sich kaum: Sie rufen solve_captcha mit der Methode turnstile auf und geben das Ergebnis über das Feld cf-turnstile-response zurück.
def scrape_turnstile_market_data(url, sitekey):
"""Handle Cloudflare Turnstile on financial data sites."""
token = solve_captcha("turnstile", sitekey, url)
session = requests.Session()
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
})
resp = session.post(url, data={
"cf-turnstile-response": token,
}, timeout=30)
return resp.json() if resp.status_code == 200 else None
Turnstile-Token laufen wie reCAPTCHA-Token nach kurzer Zeit ab. Lösen Sie das Token daher unmittelbar vor der Übermittlung und halten Sie es nicht auf Vorrat.
Tägliche Marktdaten planen und speichern
Für wiederkehrende Erfassung – etwa einen Snapshot am Handelsende – kapseln Sie den Scraper in einen geplanten Job, der pro Ticker eine kurze Pause einlegt und das Ergebnis als CSV ablegt.
import csv
from datetime import datetime
def daily_market_snapshot(tickers, output_dir="data"):
"""Collect daily stock data, handling CAPTCHAs automatically."""
scraper = FinancialScraper(
proxy="http://user:pass@residential.proxy.com:5000"
)
date_str = datetime.now().strftime("%Y-%m-%d")
results = []
for ticker in tickers:
url = f"https://screener.example.com/quote.ashx?t={ticker}"
try:
data = scraper.scrape_screener(url)
if data:
results.extend(data)
time.sleep(2) # Rate limit
except Exception as e:
print(f"Error on {ticker}: {e}")
# Save to CSV
filepath = f"{output_dir}/market_{date_str}.csv"
with open(filepath, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["ticker", "company", "sector", "price", "change"])
writer.writeheader()
writer.writerows(results)
print(f"Saved {len(results)} records to {filepath}")
return results
# Run daily
tickers = ["AAPL", "GOOGL", "MSFT", "AMZN", "TSLA"]
daily_market_snapshot(tickers)
Ein solcher Nightly-Job belegt selten mehr als eine Handvoll gleichzeitiger Threads. Der Einstiegstarif BASIC (15 $/Monat, 5 Threads) deckt das in der Regel ab; wer mehrere Portale parallel abfragt, greift zu STANDARD (30 $/Monat, 15 Threads) oder ADVANCE (90 $/Monat, 50 Threads). Abgerechnet wird pro gleichzeitigem Thread – nicht pro gelöstem CAPTCHA, und die Lösungen pro Thread sind im Monat unbegrenzt.
Rate-Limiting: die Grenzen der Portale respektieren
Finanzseiten sind beim automatisierten Zugriff strenger als die meisten anderen. Konservative Grenzen senken die CAPTCHA-Rate spürbar.
Faustregel: Jedes vermiedene CAPTCHA ist eine gesparte API-Anfrage – niedrige Anfrageraten zahlen sich also doppelt aus, in Stabilität und in Kosten.
| Maßnahme | Empfehlung |
|---|---|
| Verzögerung zwischen Anfragen | 2–5 Sekunden pro Seite |
| Gleichzeitige Verbindungen | maximal 3–5 pro Domain |
| Proxy-Typ | Residential oder ISP |
| Sitzungsdauer | 5–10 Minuten Sticky-Session |
| User-Agent | realistisch, pro Sitzung konsistent |
| SEC EDGAR | Kontakt-E-Mail im User-Agent (erforderlich) |
| Handelszeiten | wenn möglich außerhalb der Hauptlast scrapen |
Häufige Fehler und ihre Ursachen
| Problem | Ursache | Lösung |
|---|---|---|
| 403 auf SEC EDGAR | User-Agent ohne E-Mail | Header CompanyName email@domain ergänzen |
| CAPTCHA bei jeder Anfrage | Rate-Limit überschritten | 3–5 Sekunden Verzögerung zwischen Anfragen einbauen |
| Veraltete Kursdaten | zwischengespeicherte Antwort | Cache-Bust-Parameter an die Abfrage hängen |
| JSON-Parsing schlägt fehl | statt Daten kam die CAPTCHA-Seite zurück | vor dem Parsen auf CAPTCHA prüfen |
| IP blockiert | zu viele Anfragen von derselben IP | auf rotierenden Residential-Proxy wechseln |
DSGVO und rechtlicher Rahmen
Öffentliche Finanzdaten wie Pflichtveröffentlichungen und Kursdaten lassen sich grundsätzlich erfassen, doch für DACH-Leser kommen zwei Punkte hinzu. Erstens gelten IP-Adressen nach der DSGVO als personenbezogene Daten – prüfen Sie Ihre Datenflüsse und die Rechtsgrundlage, sobald ein Workflow personenbezogene Informationen berührt. Zweitens sind die Nutzungsbedingungen und Rate-Limits jeder Quelle verbindlich; halten Sie diese ein und beschränken Sie sich auf öffentlich zugängliche Daten, die Sie nutzen dürfen. Diese Einschätzung ist keine Rechtsberatung – im Zweifel klären Sie den konkreten Fall mit einer fachkundigen Stelle.
FAQ
Löst CaptchaAI jedes CAPTCHA auf Finanzportalen?
CaptchaAI deckt die Typen ab, die auf Finanzseiten üblich sind: reCAPTCHA v2 und v3, Cloudflare Turnstile und Cloudflare Challenge sowie Bild- und OCR-CAPTCHAs. hCaptcha und FunCaptcha werden nicht unterstützt; GeeTest v4 ist als „bald verfügbar" angekündigt, aber noch nicht verfügbar.
Was kostet ein täglicher Marktdaten-Job?
Abgerechnet wird nach gleichzeitigen Threads, nicht pro Lösung. Ein nächtlicher Snapshot mit wenigen parallelen Anfragen passt meist in BASIC (15 $/Monat, 5 Threads). Für mehrere Portale gleichzeitig eignen sich STANDARD (30 $/Monat, 15 Threads) oder ADVANCE (90 $/Monat, 50 Threads). Alle Preise in US-Dollar.
Welcher Proxy-Typ eignet sich für Finanzseiten?
Residential- oder ISP-Proxys mit Sticky-Sessions von 5–10 Minuten. Rechenzentrums-Proxys werden von Finanzportalen schneller erkannt und lösen häufiger CAPTCHAs oder Sperren aus. Rotieren Sie die IP erst, wenn eine Blockade auftritt, nicht bei jeder Anfrage.
Wie oft sollte ich Kursdaten abrufen?
Für Kurse höchstens einmal pro Minute während der Handelszeiten, für Pflichtveröffentlichungen genügt meist ein täglicher Abruf. Häufigeres Scraping löst schneller CAPTCHAs aus und erhöht das Sperr-Risiko.
Verwandte Leitfäden
- Rotierende Residential-Proxys für die CAPTCHA-Lösung
Finanzdaten ohne CAPTCHA-Unterbrechungen erfassen – Holen Sie sich Ihren CaptchaAI-Schlüssel.