Wer Gebote, Preisverläufe und neue Einträge auf Auktionsportalen automatisch verfolgen will, stößt früher oder später auf reCAPTCHA v2 – genau bei den Aktionen, die ein Monitoring-Skript am häufigsten ausführt: schnelle Suchabfragen, wiederholte Detailansichten, das Nachladen der Gebotshistorie. Der Ablauf, der das zuverlässig löst, ist immer derselbe: CAPTCHA im Antwort-HTML erkennen, über CaptchaAI lösen lassen und die Anfrage mit dem Token erneut senden. Ihr Scraper läuft weiter, ohne dass jemand eingreifen muss.
Wann Auktionsportale ein CAPTCHA anzeigen
Ausgelöst wird die Abfrage fast immer durch das Muster der Zugriffe, nicht durch die einzelne Anfrage. reCAPTCHA v2 ist der Standardschutz, gelegentlich ergänzt durch Cloudflare Turnstile in der Kategorie-Navigation. Wer die typischen Auslöser kennt, kann sein Monitoring so takten, dass CAPTCHAs seltener erscheinen – und wenn doch, greift der automatische Lösungsweg.
| Aktion | CAPTCHA-Typ | Auslöser |
|---|---|---|
| Einträge suchen und durchblättern | reCAPTCHA v2 | Schnelle Suchabfragen in Folge |
| Eintragsdetails öffnen | reCAPTCHA v2 | Hohes Volumen von derselben IP |
| Gebotshistorie abrufen | reCAPTCHA v2 | Detailseite wiederholt geladen |
| Kategorien durchsuchen | Cloudflare Turnstile | Bot-typische Navigationsgeschwindigkeit |
| Preisalarm-Seiten | reCAPTCHA v2 | Häufige Aktualisierungen |
In vier Schritten zur laufenden Überwachung
Der Kern jeder Auktionsüberwachung folgt derselben Reihenfolge – unabhängig davon, ob Sie in Python oder JavaScript arbeiten:
- Ziel-URLs und Suchbegriffe festlegen und je Quelle eine eigene Session anlegen.
- Das Antwort-HTML auf reCAPTCHA v2 prüfen und bei Bedarf den Sitekey extrahieren.
- Das Token über CaptchaAI lösen und die Anfrage in derselben Sitzung erneut senden.
- Erst danach die Einträge parsen, Ergebnisse protokollieren und das nächste Intervall abwarten.
Auktionen überwachen und CAPTCHAs automatisch lösen
Die folgende Klasse kapselt Suche, Detailabruf und Gebotsverfolgung: Trifft eine Anfrage auf reCAPTCHA v2, wird der Sitekey extrahiert, das Token über CaptchaAI gelöst und die Anfrage in derselben Sitzung wiederholt. Entscheidend ist, dass Suche und Detailabruf dieselbe requests.Session() nutzen – so bleiben Cookies erhalten und das nächste CAPTCHA lässt oft länger auf sich warten.
import requests
import time
import re
from datetime import datetime
class AuctionMonitor:
def __init__(self, api_key):
self.api_key = api_key
self.session = requests.Session()
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})
def search_listings(self, auction_url, query, category=None):
"""Search auction listings, solving CAPTCHAs when triggered."""
params = {"q": query}
if category:
params["category"] = category
response = self.session.get(
f"{auction_url}/search", params=params
)
if self._has_captcha(response.text):
site_key = self._extract_site_key(response.text)
token = self._solve_recaptcha(site_key, f"{auction_url}/search")
response = self.session.post(
f"{auction_url}/search",
data={**params, "g-recaptcha-response": token}
)
return self._parse_listings(response.text)
def monitor_listing(self, auction_url, listing_id):
"""Get current bid and listing details."""
url = f"{auction_url}/item/{listing_id}"
response = self.session.get(url)
if self._has_captcha(response.text):
site_key = self._extract_site_key(response.text)
token = self._solve_recaptcha(site_key, url)
response = self.session.post(url, data={
"g-recaptcha-response": token
})
return self._parse_listing_detail(response.text)
def track_bids(self, auction_url, listing_ids, interval=60):
"""Track bid changes across multiple listings."""
history = {lid: [] for lid in listing_ids}
while True:
for listing_id in listing_ids:
try:
detail = self.monitor_listing(auction_url, listing_id)
previous = history[listing_id]
if previous and detail["current_bid"] != previous[-1]["current_bid"]:
print(f"Bid change on {listing_id}: "
f"${previous[-1]['current_bid']} → ${detail['current_bid']}")
history[listing_id].append(detail)
except Exception as e:
print(f"Error checking {listing_id}: {e}")
time.sleep(interval)
def _has_captcha(self, html):
return "g-recaptcha" in html or "recaptcha" in html.lower()
def _extract_site_key(self, html):
match = re.search(r'data-sitekey="([^"]+)"', html)
if match:
return match.group(1)
match = re.search(r"sitekey['\"]?\s*[:=]\s*['\"]([^'\"]+)", html)
if match:
return match.group(1)
raise ValueError("Could not find reCAPTCHA site key")
def _solve_recaptcha(self, site_key, page_url):
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": self.api_key,
"method": "userrecaptcha",
"googlekey": site_key,
"pageurl": page_url,
"json": 1
})
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(3)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": self.api_key,
"action": "get",
"id": task_id,
"json": 1
})
data = result.json()
if data["status"] == 1:
return data["request"]
raise TimeoutError("reCAPTCHA solve timed out")
def _parse_listings(self, html):
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
def text_or_none(node):
return node.text.strip() if node and node.text else None
def attr_or_none(node, attr):
return node.get(attr) if node else None
listings = []
for item in soup.select(".listing-item, .auction-item"):
listings.append({
"title": text_or_none(item.select_one(".title")),
"current_bid": text_or_none(item.select_one(".price, .bid")),
"time_left": text_or_none(item.select_one(".time-left")),
"url": attr_or_none(item.select_one("a"), "href")
})
return listings
def _parse_listing_detail(self, html):
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
def text_or_none(node):
return node.text.strip() if node and node.text else None
return {
"title": text_or_none(soup.select_one("h1, .item-title")),
"current_bid": text_or_none(soup.select_one(".current-bid, .price")),
"bid_count": text_or_none(soup.select_one(".bid-count")),
"time_left": text_or_none(soup.select_one(".time-remaining")),
"checked_at": datetime.now().isoformat()
}
# Usage
monitor = AuctionMonitor("YOUR_API_KEY")
listings = monitor.search_listings(
"https://auctions.example.com",
"vintage electronics",
category="collectibles"
)
Preisalarme in JavaScript umsetzen
Für ereignisgesteuerte Alarme genügt ein schlanker Tracker: Er beobachtet eine Liste von Einträgen und meldet, sobald ein Gebot in die Nähe Ihrer Preisgrenze rückt – hier bei 90 % des Höchstgebots. Auch dieser Tracker erkennt ein reCAPTCHA v2, löst es über CaptchaAI und wiederholt die Anfrage, bevor er die Detailseite auswertet.
class AuctionTracker {
constructor(apiKey) {
this.apiKey = apiKey;
this.watchList = new Map();
}
addWatch(listingId, url, maxPrice) {
this.watchList.set(listingId, { url, maxPrice, history: [] });
}
async checkAll() {
const alerts = [];
for (const [id, watch] of this.watchList) {
try {
const detail = await this.fetchListing(watch.url);
watch.history.push(detail);
const price = parseFloat(detail.currentBid.replace(/[^0-9.]/g, ''));
if (price >= watch.maxPrice * 0.9) {
alerts.push({
listing: id,
price,
threshold: watch.maxPrice,
message: `Price approaching limit: $${price} / $${watch.maxPrice}`
});
}
} catch (error) {
alerts.push({ listing: id, error: error.message });
}
}
return alerts;
}
async fetchListing(url) {
const response = await fetch(url);
const html = await response.text();
if (html.includes('g-recaptcha')) {
return this.solveAndFetch(url, html);
}
return this.parseDetail(html);
}
async solveAndFetch(url, html) {
const siteKeyMatch = html.match(/data-sitekey="([^"]+)"/);
if (!siteKeyMatch) throw new Error('No reCAPTCHA site key found');
const submitResp = await fetch('https://ocr.captchaai.com/in.php', {
method: 'POST',
body: new URLSearchParams({
key: this.apiKey,
method: 'userrecaptcha',
googlekey: siteKeyMatch[1],
pageurl: url,
json: '1'
})
});
const { request: taskId } = await submitResp.json();
for (let i = 0; i < 60; i++) {
await new Promise(r => setTimeout(r, 3000));
const result = await fetch(
`https://ocr.captchaai.com/res.php?key=${this.apiKey}&action=get&id=${taskId}&json=1`
);
const data = await result.json();
if (data.status === 1) {
// Resubmit with token
const response = await fetch(url, {
method: 'POST',
body: new URLSearchParams({ 'g-recaptcha-response': data.request })
});
return this.parseDetail(await response.text());
}
}
throw new Error('reCAPTCHA solve timed out');
}
parseDetail(html) {
// Parse auction listing details from HTML
return {
currentBid: html.match(/current.?bid[^>]*>([^<]+)/i)?.[1]?.trim(),
bidCount: html.match(/(\d+)\s*bids?/i)?.[1],
timeLeft: html.match(/time.?(?:left|remaining)[^>]*>([^<]+)/i)?.[1]?.trim(),
checkedAt: new Date().toISOString()
};
}
}
// Usage
const tracker = new AuctionTracker('YOUR_API_KEY');
tracker.addWatch('item-123', 'https://auctions.example.com/item/123', 500);
tracker.addWatch('item-456', 'https://auctions.example.com/item/456', 200);
const alerts = await tracker.checkAll();
Die Methode track_bids aus dem Python-Beispiel ergänzt diesen Ansatz um eine Verlaufsprüfung: Sie hält je Eintrag eine Historie vor und meldet nur echte Gebotsänderungen. In Kombination lassen sich so Preisgrenzen (JavaScript) und Gebotsdynamik (Python) getrennt überwachen, ohne bei jedem Durchlauf die volle Detailseite neu zu parsen.
Prüfintervall und erwartete CAPTCHA-Last
Wie oft ein CAPTCHA erscheint, hängt direkt vom Prüfintervall ab. Je enger der Takt, desto eher werten Auktionsportale die Zugriffe als automatisiert – und desto häufiger schaltet sich reCAPTCHA v2 dazwischen. Wählen Sie das gröbste Intervall, das Ihr Anwendungsfall noch zulässt.
| Prüfintervall | Anwendungsfall | Erwartete CAPTCHA-Rate |
|---|---|---|
| Alle 30 Sekunden | Gebote in letzter Minute | Hoch – Proxys einsetzen |
| Alle 5 Minuten | Aktive Auktionsverfolgung | Mäßig |
| Alle 15 Minuten | Beobachtungsliste im Blick behalten | Niedrig |
| Stündlich | Langfristige Preisrecherche | Minimal |
CAPTCHAs von vornherein reduzieren
Jede vermiedene Abfrage spart Threads und Laufzeit; die wirksamsten Hebel setzen beim Zugriffsmuster an.
| Technik | Wirkung |
|---|---|
| Session-Cookies wiederverwenden | Hält den angemeldeten Zustand aufrecht |
| Residential-Proxys rotieren | Verteilt Anfragen auf mehrere IPs |
| Anfrageintervalle zufällig variieren | Vermeidet periodische Erkennungsmuster |
| Angemeldete Konten nutzen | Niedrigere CAPTCHA-Schwellen |
Ein Hinweis für den DACH-Raum: Sobald Sie Residential-Proxys einsetzen, verarbeiten Sie fremde IP-Adressen – nach DSGVO ein personenbezogenes Datum. Prüfen Sie vorab Ihre Rechtsgrundlage und die Nutzungsbedingungen des jeweiligen Auktionsportals, bevor Sie ein Monitoring produktiv schalten. Für Worker und geplante Jobs bieten sich Anbieter wie Hetzner oder netcup an; die Zeitpläne lassen sich bequem über GitLab CI oder GitHub Actions steuern.
Typische Probleme beim Auktions-Monitoring
| Problem | Ursache | Lösung |
|---|---|---|
| Zu viele CAPTCHAs in kurzer Zeit | Abrufrate oder Parallelität ist für die Quelle zu aggressiv | Intervalle drosseln, Sessions stabil halten und die Proxy-Qualität prüfen |
| Trotz gelöstem CAPTCHA fehlen Daten | Der Parser liest eine veraltete oder unvollständige Ansicht aus | Daten erst nach erfolgreicher Token-Übermittlung in derselben Sitzung auslesen |
| reCAPTCHA-Token wird abgelehnt | Token ist nach rund 2 Minuten abgelaufen | Token unmittelbar vor dem Absenden lösen |
| Kosten steigen stärker als erwartet | Unnötige Wiederholungen und Seitenaufrufe lösen zusätzliche Abfragen aus | Nur kritische Schritte lösen und Wiederholungen je Quelle protokollieren |
Häufige Fragen
Welche CAPTCHA-Typen treten auf Auktionsseiten auf?
Überwiegend reCAPTCHA v2 – bei Suche, Detailansichten und Gebotshistorie; beim Durchblättern von Kategorien gelegentlich Cloudflare Turnstile. CaptchaAI löst beide über dieselbe API.
Wie viele Auktionen kann ich gleichzeitig überwachen?
So viele, wie Ihr Plan an Threads bereitstellt. Jeder Thread verarbeitet eine laufende CAPTCHA-Abfrage und übernimmt nach der Lösung sofort die nächste. BASIC (15 $/Monat, 5 Threads) genügt für mehrere parallele Einträge; größere Beobachtungslisten profitieren von STANDARD oder ADVANCE.
Warum werden trotz gelöstem CAPTCHA keine Einträge geladen?
Meist stimmt die Reihenfolge nicht: Der Parser liest die Seite, bevor das Token angewendet wurde. Extrahieren Sie Einträge erst nach erfolgreicher Token-Übermittlung in derselben Sitzung.
Was kostet die Auktionsüberwachung?
Abgerechnet wird pro parallelem Thread, nicht pro Einzellösung – innerhalb eines Plans lösen Sie unbegrenzt viele CAPTCHAs. Für gelegentliches Monitoring reicht BASIC (15 $/Monat, 5 Threads); wer viele Einträge im Sekundentakt prüft, skaliert über STANDARD oder ADVANCE nach oben. Die Preise sind in US-Dollar und richten sich allein nach der Zahl paralleler Threads.
Brauche ich Residential-Proxys für die Überwachung?
Nicht zwingend, aber bei kurzen Intervallen sehr hilfreich. Rotierende Residential-Proxys verteilen Ihre Anfragen auf mehrere IPs und senken die CAPTCHA-Rate spürbar. Bei stündlichen Prüfungen genügt oft eine stabile Session ganz ohne Proxy.
Verwandte Leitfäden
- CaptchaAI in wenigen Minuten einrichten
- API-Antwortformate und Fehlercodes
- reCAPTCHA v2 per API lösen