Zum Inhalt springen
API-Leitfäden

IP-Betrugserkennungs-API: Registrierungen, Logins und Checkouts in Node und Python bewerten

Bauen Sie eine IP-Betrugserkennungs-API in Registrierung, Login und Checkout ein: Node- und Python-Code, getestet an sechs öffentlichen IPs, mit echter Ausgabe, Caching und Rate-Limits.

VonGeoIPHub-TeamVeröffentlichtAktualisiertLesezeit15 Min. Lesezeit
Ein App-Fenster, in das ein leuchtendes Kabel von einem hellen Knoten eingesteckt ist, als Sinnbild für IP-Betrugserkennung mit einem einzigen API-Aufruf

Zwei Registrierungen kommen im Abstand von einer Sekunde an, und beide verbergen die Heimadresse der Person. Eine kommt von einem Tor-Exit in Hamburg. Die andere kommt von iCloud Private Relay, das Apple als „part of an iCloud+ subscription“ (Teil eines iCloud+-Abonnements) beschreibt, der Sie schützt, „when you browse the web in Safari“ (wenn Sie in Safari im Web surfen) (Apple Support). Eine Regel, die „alles Verborgene“ blockiert, lehnt beide ab, und eine davon ist eine zahlende Apple-Kundin.

Diese beiden auseinanderzuhalten ist die Aufgabe. Sie ist ein Ausschnitt dessen, was IP-Intelligence abdeckt, und sie passt in eine einzige Datei mit weniger als 50 Zeilen. Unten finden Sie die Anfrage, eine echte Antwort, eine Node- und eine Python-Version mit Caching und Fehlerbehandlung, was beide für sechs Adressen ausgegeben haben und wo die Prüfung an Grenzen stößt.

Eine Stoppuhr neben einem App-Fenster, das sich mit einer Antwortkarte füllt, als Sinnbild für eine Integration in wenigen Minuten
Eine Anfrage, eine Antwort, alle Felder.

Die eine Anfrage, die eine IP-Betrugserkennungs-API braucht

Die gesamte Integration ist ein einziges GET mit der IP im Pfad und Ihrem Schlüssel im Header x-api-key. Die API-Referenz dokumentiert dieselbe Form:

GeoIPHub API
curl https://api.geoiphub.com/v1/lookup/45.83.220.7 \ -H "x-api-key: YOUR_API_KEY"

Drei Details erwischen viele beim ersten Versuch:

  • Die IP gehört in den Pfad. /v1/lookup/{ip} ist die einzige Form. Eine Variante mit Query-String leitet weiter, statt Daten zu liefern.
  • Senden Sie nicht den Platzhalter. Wir haben den wörtlichen String YOUR_API_KEY gesendet und 401 mit {"message":"Invalid API key"} erhalten. Lassen Sie den Header weg, bis Sie einen echten Schlüssel haben; anonyme Aufrufe funktionieren mit 30 pro Minute.
  • Eine IP pro Aufruf. Jede Anfrage nimmt eine Adresse entgegen, ein Skript, das eine Liste prüft, stellt also pro Adresse eine Anfrage, und jede zählt gegen Ihr Limit.

Erstellen Sie im Dashboard einen kostenlosen Schlüssel, sobald Sie über das Testen hinaus sind. Der kostenlose Tarif gibt diesem Schlüssel 1.500 Abfragen pro Tag, mit allen Feldern.

Was für eine Mullvad-Adresse zurückkam und nach welchen Feldern Sie verzweigen

Die Antwort umfasst etwa 2,7 KB verschachteltes JSON in zehn Gruppen, und eine Betrugsprüfung braucht zwei davon: detection und scoring. Hier ist die Abfrage für 45.83.220.7, gekürzt, aber mit unveränderten Werten:

GeoIPHub API
{ "ip": "45.83.220.7", "asn": { "asn": 39351, "org": "ESAB-AS - 31173 Services AB", "asn_type": "hosting", "connection_type": "datacenter" }, "geo": { "country_code": "SE", "city": "Malmö" }, "detection": { "is_vpn": true, "is_proxy": false, "is_tor": false, "is_hosting": true, "is_relay": false, "vpn_provider": "Mullvad (31173 Services)", "vpn_confidence": 85 }, "scoring": { "fraud_score": 46, "confidence": 0.56, "recommended_action": "review", "detection_methods": [ "known_vpn_server", "datacenter_ip" ] }, "meta": { "last_classified_at": "2026-10-16T07:40:17.524Z" } }

Diese Adresse liegt bei 31173 Services in Malmö, dem Netzwerk, in dem Mullvad VPN seine Server betreibt. Als wir am 13. Oktober nachsahen, stand sie nicht auf der von Mullvad selbst veröffentlichten Serverliste. Zwei Signale schlugen an. known_vpn_server stammt aus unserer Tabelle bekannter VPN-Hosting-Netzwerke, deshalb liegt vpn_confidence bei 85 und nicht bei den 95, die ein Treffer auf Mullvads eigener Serverliste ergibt. datacenter_ip besagt, dass es sich um Hosting handelt, nicht um einen Heimanschluss. Zusammen ergeben sie einen Score von 46, der in review landet: Ein VPN allein ist kein Betrug.

Drei Felder tragen die Entscheidung:

FeldWas es enthältWie der Code es nutzt
scoring.recommended_actionallow (Score bis 25), review (bis 50), step_up (bis 75), block (über 75)Die Verzweigung
scoring.fraud_scoreDer zusammengesetzte Wert von 0 bis 100 hinter dieser AktionProtokollierung und spätere Feinabstimmung
scoring.detection_methodsDie Signale, die angeschlagen haben, etwa tor_exit oder openvpn_openDer Grund, den Sie speichern und Prüfern anzeigen

Die detection-Flags (is_vpn, is_proxy, is_tor, is_hosting, is_relay) sind die Rohfakten hinter dem Score. Nutzen Sie sie für die wenigen Regeln, bei denen Ihr Geschäft von den Standardbereichen abweicht. Der Score kennt auch entlastende Signale: Ein Privatkunden-ISP zieht 20 Punkte ab und ein verifizierter Crawler 30, ein Flag allein schiebt eine Adresse also nicht in block. Der Leitfaden zum IP-Betrugsscore erklärt, was die Zahl bewegt.

Die Node-Version: fetch, ein Cache für eine Stunde und vier Zweige

Dies ist genau die Datei, die wir ausgeführt haben, auf Node 24 ohne Abhängigkeiten. Sie benötigt Node 18 oder neuer für das eingebaute fetch:

GeoIPHub API
// screen.mjs: score an IP before a signup, login or checkout. Node 18+, no dependencies. const API = "https://api.geoiphub.com/v1/lookup/"; const KEY = process.env.GEOIPHUB_API_KEY; // without a key: 30 lookups a minute, for testing only const TTL_MS = 60 * 60 * 1000; // reuse a verdict for an hour const cache = new Map(); // ip -> { at, data } async function lookup(ip) { const hit = cache.get(ip); if (hit && Date.now() - hit.at < TTL_MS) return hit.data; const headers = KEY ? { "x-api-key": KEY } : {}; const res = await fetch(API + encodeURIComponent(ip), { headers, signal: AbortSignal.timeout(3000), }); if (res.status === 429) throw new Error(`rate limited, retry after ${res.headers.get("retry-after")}s`); if (!res.ok) throw new Error(`HTTP ${res.status}`); const data = await res.json(); cache.set(ip, { at: Date.now(), data }); return data; } export async function screen(ip, flow) { let data; try { data = await lookup(ip); } catch (err) { return { action: "review", reason: `lookup failed: ${err.message}` }; // fail soft, never block on our outage } const { scoring, detection } = data; let action = scoring.recommended_action; // "allow" | "review" | "step_up" | "block" if (detection.is_tor) action = "block"; // no step-up through a Tor exit if (flow === "checkout" && action === "review") action = "step_up"; // stricter where money moves const flags = ["is_vpn", "is_proxy", "is_tor", "is_hosting", "is_relay"].filter((f) => detection[f]); return { action, score: scoring.fraud_score, flags, methods: scoring.detection_methods }; } // Try it: node screen.mjs signup 45.33.32.156 104.28.46.99 const [flow, ...ips] = process.argv.slice(2); for (const ip of ips) { const v = await screen(ip, flow); console.log(ip.padEnd(15), v.action.padEnd(8), v.score ?? "-", v.flags?.join(",") || "-", v.methods?.join(",") || v.reason); }

Vier Entscheidungen darin sind bewusst getroffen:

  • Sie geht von recommended_action aus und überschreibt den Wert nur an zwei Stellen. Ein Tor-Exit wird immer blockiert, und beim Checkout wird aus review ein step_up, weil dort Geld fließt.
  • Sie scheitert weich. Ein Timeout, ein 5xx oder ein 429 liefert review, nicht block. Ist unsere API nicht erreichbar, funktionieren Ihre Registrierungen weiter und werden für einen zweiten Blick protokolliert.
  • Das Timeout beträgt 3 Sekunden. Auf unserer Seite wird eine bekannte IP aus einer per Memory-Mapping eingebundenen Datenbank in unter einer Millisekunde beantwortet, den größten Teil der Wartezeit macht also der Netzwerk-Roundtrip aus. Eine IP, die wir noch nie gesehen haben, wird live in unter 2,5 Sekunden klassifiziert, und 3 Sekunden decken diesen Fall ab.
  • Der Schlüssel bleibt auf Ihrem Server. Rufen Sie die API aus Ihrem Backend auf, niemals aus Browser-Code, in dem jeder den Schlüssel lesen kann.

Die Python-Version braucht einen User-Agent, sonst gibt es einen 403

Unsere API beantwortet den Standard-User-Agent von Python urllib, Python-urllib/3.x, mit 403 Forbidden. Wir haben das am 16. Oktober um 05:36 UTC mit einem nackten Aufruf von urllib.request.urlopen nachgestellt: HTTP Error 403: Forbidden. Curl und requests sind nicht betroffen, weil sie andere User-Agents senden. Die Python-Datei setzt deshalb einen eigenen, mit einem Kommentar, der den Grund nennt:

GeoIPHub API
# screen.py: score an IP before a signup, login or checkout. Python 3.8+, standard library only. import json, os, sys, time, urllib.error, urllib.request API = "https://api.geoiphub.com/v1/lookup/" KEY = os.environ.get("GEOIPHUB_API_KEY") # without a key: 30 lookups a minute, for testing only TTL = 3600 # reuse a verdict for an hour _cache = {} # ip -> (time, data) def lookup(ip): hit = _cache.get(ip) if hit and time.time() - hit[0] < TTL: return hit[1] # Set a User-Agent: our API answers urllib's default "Python-urllib/3.x" with 403 Forbidden. headers = {"User-Agent": "signup-screen/1.0"} if KEY: headers["x-api-key"] = KEY req = urllib.request.Request(API + ip, headers=headers) with urllib.request.urlopen(req, timeout=3) as resp: data = json.load(resp) _cache[ip] = (time.time(), data) return data def screen(ip, flow): try: data = lookup(ip) except urllib.error.HTTPError as e: wait = e.headers.get("Retry-After") if e.code == 429 else None return {"action": "review", "reason": f"HTTP {e.code}" + (f", retry after {wait}s" if wait else "")} except (OSError, ValueError) as e: # network error, timeout, bad JSON return {"action": "review", "reason": f"lookup failed: {e}"} # fail soft scoring, detection = data["scoring"], data["detection"] action = scoring["recommended_action"] # "allow" | "review" | "step_up" | "block" if detection["is_tor"]: action = "block" # no step-up through a Tor exit if flow == "checkout" and action == "review": action = "step_up" # stricter where money moves flags = [f for f in ("is_vpn", "is_proxy", "is_tor", "is_hosting", "is_relay") if detection[f]] return {"action": action, "score": scoring["fraud_score"], "flags": flags, "methods": scoring["detection_methods"]} if __name__ == "__main__": flow, ips = sys.argv[1], sys.argv[2:] for ip in ips: v = screen(ip, flow) print(f"{ip:<15} {v['action']:<8}", v.get("score", "-"), ",".join(v.get("flags", [])) or "-", ",".join(v.get("methods", [])) or v.get("reason", ""))

Es ist dieselbe Logik wie in der Node-Datei, nur mit der Standardbibliothek, getestet auf Python 3.9.6. urllib löst bei jedem Status außerhalb von 2xx einen HTTPError aus, daher werden der 429 und sein Retry-After-Header aus der Exception gelesen.

Was beide Skripte für sechs öffentliche Adressen ausgegeben haben

Beide Skripte lieferten für jede Adresse dasselbe Urteil. Wir haben die Node-Datei am 16. Oktober 2026 um 07:39 UTC und die Python-Datei um 07:40 UTC ausgeführt, ohne Schlüssel, gegen sechs öffentliche Adressen. Der letzte Befehl führt die Mullvad-Adresse erneut als Checkout aus:

GeoIPHub API
node screen.mjs signup 45.33.32.156 104.28.46.99 45.83.220.7 91.90.122.25 102.129.235.17 185.220.101.1 node screen.mjs checkout 45.83.220.7
GeoIPHub API
45.33.32.156 allow 10 is_hosting datacenter_ip 104.28.46.99 allow 9 is_relay relay_ip 45.83.220.7 review 46 is_vpn,is_hosting known_vpn_server,datacenter_ip 91.90.122.25 step_up 64 is_hosting datacenter_blocklisted,no_ptr_datacenter,known_spammer 102.129.235.17 block 92 is_vpn known_vpn_server,openvpn_open,ipsec_open 185.220.101.1 block 100 is_tor,is_hosting tor_exit,datacenter_blocklisted,no_ptr_datacenter,known_spammer 45.83.220.7 step_up 46 is_vpn,is_hosting known_vpn_server,datacenter_ip

python3 screen.py mit denselben Argumenten gab dieselben sieben Zeilen aus, Zeichen für Zeichen. Hier sehen Sie, was jede Adresse ist und warum sie dort gelandet ist, wo sie gelandet ist:

AdresseWas sie istAktionAngeschlagene Signale
45.33.32.156scanme.nmap.org, der öffentliche Testhost von Nmap bei Linodeallow, 10Nur datacenter_ip. Hosting allein ist kein Betrug
104.28.46.99Egress von iCloud Private Relay bei Cloudflareallow, 9relay_ip. Der Score deckelt Relay-Adressen bei 60, sie können block also nie erreichen
45.83.220.7Mullvads Netzwerk in Malmöreview, 46; step_up beim Checkoutknown_vpn_server, datacenter_ip
91.90.122.25VPN-Server von PIA in Schaan, Liechtenstein, bei M247step_up, 64datacenter_blocklisted, no_ptr_datacenter, known_spammer. Nicht als VPN markiert
102.129.235.17Kommerzieller VPN-Server in Washington, D.C.block, 92known_vpn_server, dazu openvpn_open und ipsec_open: Unsere Probes haben OpenVPN- und IPsec-Handshakes abgeschlossen
185.220.101.1Tor-Exit in Hamburgblock, 100tor_exit, datacenter_blocklisted, no_ptr_datacenter, known_spammer

Die beiden Registrierungen vom Anfang landeten an entgegengesetzten Enden: der Tor-Exit bei 100 und die Private-Relay-Nutzerin bei 9. Diese Spannweite ist der Grund, zu bewerten, statt jede verborgene Adresse zu blockieren.

Die Ergebnisse ändern sich, wenn sich unsere Daten ändern. Bis zu dieser Überarbeitung zeigte dieser Beitrag 45.83.220.7 als reines Hosting mit einem Score von 10 und allow. Bis zum 8. Oktober hatte unser Scanner die Adresse Mullvad zugeordnet, und jetzt liegt ihr Score bei 46. Protokollieren Sie zu jeder Entscheidung die Aktion und die Methoden, damit eine solche Änderung in Ihren Daten sichtbar wird, statt Sie zu überraschen.

Wo Sie die API aufrufen: bei jeder Registrierung, jedem Login und jedem Checkout

Bewerten Sie jede Registrierung, jeden Login und jeden Checkout, auf dem Server, bevor Sie die Aktion ausführen. Das sind die drei Momente, in denen ein Betrüger etwas gewinnt, und sie kommen pro Nutzer selten genug vor, um in ein Tagesbudget zu passen. Rufen Sie die API nicht bei jedem Seitenaufruf auf.

Was jede Aktion in der Praxis bedeutet:

AktionRegistrierungLoginCheckout
allowKonto anlegenAnmeldenZahlung annehmen
reviewAnlegen, zur Prüfung markierenAnmelden, Grund protokollierenUnser Code stuft es zu step_up hoch
step_upZuerst E-Mail oder Telefon verifizierenZweiten Faktor abfragen3-D Secure ausführen
blockMit neutraler Meldung ablehnenAblehnen und für die Sperre mitzählenBestellung ablehnen

Die Standardbereiche sind ein Ausgangspunkt, und Ihre eigenen Betrugsdaten sollten sie verschieben. Unser Beitrag zu Schwellenwerten des Betrugsscores für Login, Registrierung und Checkout nennt Startwerte pro Aktion und die Begründung für jeden.

Bewerten Sie auch die richtige Adresse. Hinter einem Load Balancer oder CDN ist die Socket-Adresse Ihr Proxy, und die IP des Clients steht in einem Forwarding-Header, den jeder Client auch fälschen kann. Nehmen Sie sie aus dem Hop, den Ihr eigener vertrauenswürdiger Proxy hinzugefügt hat, niemals aus dem Wert ganz links, den ein Client gesendet hat.

Unter 1.500 Abfragen pro Tag bleiben: Caching und das Rate-Limit

Der kostenlose Tarif erlaubt 1.500 Abfragen pro Tag. Cachen Sie in Ihrem eigenen Code pro IP, und das Budget reicht viel weiter, denn eine Person registriert sich, meldet sich an und bezahlt meist innerhalb einer Stunde von derselben Adresse aus.

Die API selbst hilft beim Caching nicht: Jede Antwort trägt Cache-Control: private, no-store, kein gemeinsam genutzter HTTP-Cache wird sie also speichern. Beide Skripte halten ein Urteil eine Stunde lang im Prozessspeicher. Verwenden Sie Redis oder Ihren vorhandenen Cache, wenn Sie mehr als einen Server betreiben. Behalten Sie ein Urteil nicht länger als einen Tag, denn unsere Threat-Feeds und die Lookup-Datenbank werden täglich aktualisiert.

Die beiden Limits verhalten sich unterschiedlich, und eines davon haben wir beim Testen für diesen Beitrag ausgelöst:

Aufruf alsLimitWas danach passiert
Ohne Schlüssel30 Abfragen pro Minute pro aufrufender IPDie 30. Anfrage innerhalb einer Minute liefert 429 und sperrt diese IP für zwei Stunden
Kostenloser Schlüssel1.500 Abfragen pro Tag429 mit einem Retry-After-Header, bis der Tageszähler zurückgesetzt wird

Am 16. Oktober um 05:37 UTC haben wir eine Salve anonymer Anfragen abgefeuert, um den 429 zu sehen. Innerhalb von zwanzig Sekunden lieferte die API 429 mit Retry-After: 7199, und jeder anonyme Aufruf von unserer IP blieb zwei Stunden lang gesperrt, auch unsere eigenen Skripte. Ihr Fail-soft-Pfad war die erste echte Ausgabe, die wir bekamen:

GeoIPHub API
45.33.32.156 review - - lookup failed: rate limited, retry after 6971s 45.33.32.156 review - - HTTP 429, retry after 6970s

Betrachten Sie das anonyme Limit also als Kontingent zum Testen und verwenden Sie in der Produktion einen Schlüssel. Verzweigen Sie nach dem Statuscode und Retry-After, nicht nach dem Meldungstext des 429.

Wo diese Prüfung an Grenzen stößt

Ein IP-Urteil ist ein Signal, und es übersieht Dinge. Vier Fälle sind uns beim Schreiben dieses Beitrags begegnet:

  • Ein gelisteter VPN-Server kann sauber zurückkommen. Der PIA-Server 91.90.122.25 stand am 4. Oktober auf PIAs eigener veröffentlichter Liste, trotzdem liefert unsere API is_vpn: false. Er erreichte step_up nur, weil er auf einer DNS-Blocklist steht. Ohne diese Vorgeschichte wäre er als reines Hosting durchgegangen.
  • Residential Proxys sind für IP-Daten größtenteils unsichtbar. Traffic, der über echte Heimanschlüsse geleitet wird, sieht aus wie ein Heimnutzer. Das Feld is_residential_proxy ist eine grobe Ableitung aus dem Netzwerk, keine Erkennung, bauen Sie also keine Regel darauf.
  • Geteilte Adressen tragen die Vorgeschichte anderer. Mobilfunkanbieter und CGNAT setzen viele Nutzer hinter eine IP, deshalb deckelt der Score CGNAT-Bereiche, und deshalb sollte block dort selten bleiben.
  • Relay-Standorte sind ungefähr. Für 104.28.46.99 nennt unsere Geolokalisierung Luanda, Angola, während Apples eigene Egress-Liste diesen Bereich in Lusaka, Sambia, verortet. Nutzen Sie für Entscheidungen das Relay-Flag, nicht die Stadt, wie unser Leitfaden zum Durchlassen von Private Relay erklärt.

Kombinieren Sie die IP-Prüfung mit dem, was Sie über das Konto wissen: Alter der E-Mail-Adresse, Gerät, Zahlungshistorie und Velocity. Der Leitfaden zum Payment-Fraud-Stack zeigt, wo IP-Signale darin ihren Platz haben.

Testen Sie es zuerst mit Ihrem eigenen Traffic

Bevor Sie die Prüfung in einen Live-Ablauf einbauen, lassen Sie eines der Skripte mit einem kostenlosen Schlüssel über die Registrierungs-IPs eines vergangenen Tages laufen und vergleichen Sie die Aktionen mit dem, was Sie über diese Konten bereits wissen. Wenn block Konten erwischt hätte, die Sie später gesperrt haben, und allow die Kunden abdeckt, die Sie behalten haben, setzen Sie die Prüfung zuerst vor die Registrierung, dann vor den Login, dann vor den Checkout. Um eine einzelne Adresse von Hand zu prüfen, zeigt der IP-Betrugsscore-Checker denselben Score und dieselben Gründe ganz ohne Code.

Häufig gestellte Fragen

Ist die GeoIPHub-API für den Einstieg kostenlos?

Ja. Der kostenlose Tarif umfasst 1.500 Abfragen pro Tag mit allen Datenfeldern, einen API-Schlüssel und keine Kreditkarte. Ohne Schlüssel können Sie zum Testen 30 Abfragen pro Minute ausführen.

Nach welchem Feld sollte mein Code verzweigen?

Nach scoring.recommended_action. Der Wert ist allow bis zu einem Score von 25, review bis 50, step_up bis 75 und block über 75. Lesen Sie scoring.detection_methods, um den Grund zu protokollieren.

Warum bekommt mein Python-Skript einen 403?

Unsere API beantwortet den Standard-User-Agent von urllib, Python-urllib/3.x, mit 403 Forbidden. Setzen Sie einen eigenen User-Agent-Header, und dieselbe Anfrage liefert 200.

Kann ich die Antwort cachen?

Ja, in Ihrem eigenen Code. Die API sendet Cache-Control: private, no-store, gemeinsam genutzte HTTP-Caches speichern sie also nicht. Wir verwenden ein Urteil pro IP eine Stunde lang wieder.

Blockiert das meine echten Kunden?

Nicht, wenn Sie die vier Aktionen wie vorgesehen nutzen. Eine Adresse von iCloud Private Relay kam in unserem Test mit allow und einem Score von 9 zurück, ein gewöhnlicher Cloud-Server mit allow und 10. Nur der Tor-Exit und ein per Probing verifiziertes VPN erreichten block.

Muss ich personenbezogene Daten senden?

Nein. Sie senden eine IP-Adresse und erhalten Informationen über diese Adresse. Namen, E-Mail-Adressen und Kartendaten bleiben in Ihrem System.

Verfasst von

GeoIPHub-Team

Das Team hinter der GeoIPHub-API

Verfasst vom GeoIPHub-Team, den Menschen, die die GeoIPHub-API für IP-Intelligence und ihren Scanner entwickeln. Entwürfe entstehen mit KI-Unterstützung und werden vom Team redigiert; API-Beispiele sind echte Abfragen gegen die Live-API, sofern nicht als illustrativ gekennzeichnet.

Artikel teilen
Weitere Artikel

Verwandte Beiträge