Mit Python kannst Du Telefonnummern aus LinkedIn-Profilen finden, indem Du öffentliche Profil-URLs im Format linkedin.com/in/... an die Waterfall Phone Finder API von Datablist sendest. Die API prüft nacheinander geeignete Telefondatenanbieter und gibt gefundene Nummern im internationalen Format inklusive Ländercode zurück.

In diesem Guide setzen wir mit der Requests-Bibliothek eine vollständige Python-Integration um. Anschließend verwenden wir dieselben Ergebnisse, um eine lokale Anrufliste für den Vertrieb zu erstellen, die den Namen, die LinkedIn-URL und den Account Owner jedes Prospects enthält.

📌 Kurzfassung für alle, die wenig Zeit haben

Nutze eine einzige API, um Telefonnummern anhand einer Liste öffentlicher LinkedIn-Profil-URLs zu finden. Erstelle daraus anschließend eine lokale Anrufliste mit dem Namen und Account Owner jedes Prospects. Der Waterfall Phone Finder testet geeignete Anbieter nacheinander und stellt gefundene Nummern für die Prüfung durch Dein Team bereit.

  • Input: Prospect-Datensätze mit einer öffentlichen LinkedIn-Profil-URL.
  • Output: Eine lokale Anrufliste mit gefundenen internationalen Telefonnummern, Ländercodes, Namen und Account Ownern.

💡 Du bevorzugst eine No-Code-Lösung? Nutze den Waterfall Phone Finder von Datablist, um Telefonnummern anhand von LinkedIn-Profil-URLs zu finden – ganz ohne Code.

Wenn Du statt Profil-URLs nur Namen hast, folge zuerst dem No-Code-Workflow vom Namen zur Telefonnummer oder finde LinkedIn-Profile aus Namen mit Python.

Python, Requests und Datablist API Key einrichten

Für dieses Python-Beispiel verwende ich das Paket requests. Erstelle einen Projektordner, aktiviere eine virtuelle Umgebung, installiere Requests und lege die Skriptdatei an:

shell
mkdir waterfall-phone-lookup
cd waterfall-phone-lookup
python -m venv .venv
source .venv/bin/activate
python -m pip install requests
touch find_phone_numbers.py
export DATABLIST_API_KEY="your-api-key"

Erstelle in Deinem Datablist-Konto einen Personal API Key und verwende ihn für DATABLIST_API_KEY. Der Zugriff auf die REST API ist im Growth-Plan enthalten. Auf die Credits für erfolgreiche Suchen gehe ich später in diesem Guide ein.

Telefonnummern mit einer Python-Funktion finden

Das Beispiel nutzt drei editierbare Prospect-Datensätze. Jeder Datensatz enthält eine stabile prospect_id, einen Namen, eine öffentliche LinkedIn-URL und den Account Owner, der für die Prüfung des Ergebnisses zuständig ist:

  • Florian Poullin unter https://www.linkedin.com/in/florianpoullin/
  • Satya Nadella unter https://www.linkedin.com/in/satyanadella/
  • Reid Hoffman unter https://www.linkedin.com/in/reidhoffman/

Nur die stabile ID und die LinkedIn-URL müssen an die API gesendet werden. Name und Account Owner bleiben in Deinem lokalen Quelldatensatz. So bleibt die Lookup-Anfrage kompakt, während alle geschäftlich relevanten Angaben erhalten bleiben, die Dein Team nach der Rückgabe des Ergebnisses benötigt.

Füge dieses vollständige Skript in find_phone_numbers.py ein:

python
import json
import os
import time
import uuid
import requests
def find_phone_numbers(prospects, api_key, settings):
"""Eine Telefonsuche starten, abwarten und alle Ergebnisse zurückgeben."""
tasks_url = "https://api.datablist.com/v1/enrichments/tasks"
headers = {"X-API-Key": api_key}
inputs = [
{
"inputId": prospect["prospect_id"],
"data": {"profileUrl": prospect["linkedin_url"]},
}
for prospect in prospects
]
unique_id = str(uuid.uuid4())
print(f"Task uniqueId: {unique_id}", flush=True)
payload = {
"enrichmentId": "waterfall-phone-finder",
"uniqueId": unique_id,
"settings": settings,
"inputs": inputs,
}
response = requests.post(tasks_url, headers=headers, json=payload)
response.raise_for_status()
task = response.json()
task_id = task["@id"]
task_url = f"{tasks_url}/{task_id}"
while task["status"] not in ("completed", "failed", "stopped"):
time.sleep(3)
response = requests.get(task_url, headers=headers)
response.raise_for_status()
task = response.json()
if task["status"] != "completed":
raise RuntimeError(
f"Task {task_id} {task['status']}: {task.get('error')}"
)
results = []
results_url = f"{task_url}/results"
params = {"limit": 100}
while True:
response = requests.get(results_url, headers=headers, params=params)
response.raise_for_status()
page = response.json()
results.extend(page["results"])
next_cursor = page["nextCursor"]
if next_cursor is None:
break
params["cursor"] = next_cursor
return results
if __name__ == "__main__":
api_key = os.environ.get("DATABLIST_API_KEY")
if not api_key:
raise SystemExit("Lege DATABLIST_API_KEY fest, bevor Du das Skript ausführst.")
prospects = [
{
"prospect_id": "prospect-florian-poullin",
"name": "Florian Poullin",
"linkedin_url": "https://www.linkedin.com/in/florianpoullin/",
"account_owner": "Habib",
},
{
"prospect_id": "prospect-satya-nadella",
"name": "Satya Nadella",
"linkedin_url": "https://www.linkedin.com/in/satyanadella/",
"account_owner": "Florian",
},
{
"prospect_id": "prospect-reid-hoffman",
"name": "Reid Hoffman",
"linkedin_url": "https://www.linkedin.com/in/reidhoffman/",
"account_owner": "Habib",
},
]
settings = {"cacheAge": "30"}
phone_results = find_phone_numbers(prospects, api_key, settings)
print(json.dumps(phone_results, indent=2, ensure_ascii=False))

Führe die Datei so aus:

shell
python find_phone_numbers.py

Du kannst außerdem das von Datablist gepflegte synchrone Requests-Beispiel herunterladen. Das obige Skript folgt demselben einfachen Ablauf: einen Task absenden, auf dessen Abschluss warten und alle Ergebnisseiten abrufen.

Telefonsuche starten

Die List Comprehension wandelt jeden Prospect aus der Quelldatei in das Input-Format der API um. Deine prospect_id wird zu inputId, während linkedin_url zu data.profileUrl wird. Verwende eine öffentliche Personenprofil-URL mit dem Pfad linkedin.com/in/.... Sales-Navigator-URLs werden von diesem Enrichment nicht unterstützt.

Die Funktion erzeugt eine uniqueId und gibt sie vor dem POST aus. Die Anfrage sendet diesen Wert zusammen mit der Enrichment-ID waterfall-phone-finder, der Cache-Einstellung und den Inputs. Nach erfolgreicher Übermittlung gibt die API HTTP 202 Accepted und eine Task-@id zurück, während die Verarbeitung im Hintergrund weiterläuft.

Die API-Referenz zum Waterfall Phone Finder führt die aktuellen Einstellungen, Input-Felder, Outputs, Credits und Limits auf.

Für einen Prospect hat der Request Body folgende Struktur:

json
{
"enrichmentId": "waterfall-phone-finder",
"uniqueId": "generated-uuid",
"settings": {
"cacheAge": "30"
},
"inputs": [
{
"inputId": "prospect-florian-poullin",
"data": {
"profileUrl": "https://www.linkedin.com/in/florianpoullin/"
}
}
]
}

Die öffentliche Profil-URL dient als Input für die Suche. inputId ist der Join Key, der das Ergebnis mit dem Namen und Account Owner im Quelldatensatz verknüpft. Wähle eine ID, die in Deinem eigenen System stabil und innerhalb des Tasks eindeutig ist.

Auf den Hintergrund-Task warten

Der Requests-Client blockiert lokal, während er den Task alle drei Sekunden prüft. Der Datablist-Task läuft dabei weiterhin im Hintergrund. Sobald sein Status completed lautet, ruft die Funktion die Ergebnisse ab. Bei failed oder stopped wird ein Fehler mit der Task-ID ausgelöst, damit Du den Vorgang prüfen kannst.

Alle Ergebnisseiten abrufen

Die Ergebnisanfrage ruft jeweils bis zu 100 Zeilen ab. Weitere Seiten werden geladen, bis nextCursor den Wert null hat. Jedes Ergebnis enthält seine ursprüngliche inputId, sodass Du es unabhängig von der Reihenfolge der Antworten dem richtigen Prospect zuordnen kannst.

So findet die Managed Waterfall eine Telefonnummer

Im Beispiel ist cacheAge auf "30" gesetzt. Datablist prüft zunächst, ob ein geeignetes, höchstens 30 Tage altes Ergebnis vorliegt. Ist das der Fall, kann die API es erneut verwenden. Die Einstellung erlaubt einen Cache Hit, garantiert ihn jedoch nicht.

Bleibt das Profil ungelöst, testet die Managed Waterfall nacheinander geeignete Telefondatenanbieter. Liefert ein Anbieter keine nutzbare Nummer, wird der Datensatz an den nächsten weitergegeben. Eine nutzbare Nummer beendet die Sequenz für diesen Datensatz.

Waterfall-Telefonsuche, die ohne Ergebnis fortgesetzt und beim Fund einer Telefonnummer beendet wird
Waterfall-Telefonsuche, die ohne Ergebnis fortgesetzt und beim Fund einer Telefonnummer beendet wird

Vorteile einer Waterfall über Länder und Märkte hinweg

Datablist verlässt sich nicht auf einen einzigen Telefondatenanbieter. Die Anbieter nutzen unterschiedliche Datensätze, und ihre Abdeckung variiert je nach Land und Markt. Hat ein Anbieter keine Telefonnummer, kann ein anderer sie finden. Datablist verwaltet all diese Anbieter über dieselbe API-Integration.

Für ein Vertriebsteam, das eine Anrufliste für mehrere Märkte erstellt, bedeutet das: Weniger Prospects fallen heraus, nur weil ein einzelner Anbieter kein Ergebnis liefert. Dein Python-Code sendet einen Task und verarbeitet ein einheitliches Ergebnisformat. Du musst also nicht für jeden Anbieter eine eigene Integration entwickeln und pflegen.

Setze cacheAge auf "0", wenn Dein Workflow ausdrücklich eine neue Suche anfordern soll. Für dieses Beispiel bleibt der Wert bei "30", damit ein geeignetes Cache-Ergebnis wiederverwendet werden kann.

Das vollständige Ergebnis auslesen

Hier siehst Du ein Ergebnis für Florian Poullin. Die Telefonnummer ist unten maskiert.

json
{
"inputId": "prospect-florian-poullin",
"status": "success",
"outputs": {
"finderProvider": "wizleads",
"phoneNumber": "+33 • •• •• •• ••",
"phoneNumberCountry": "FR"
},
"creditsUsed": "500",
"error": null
}

phoneNumber enthält die internationale Nummer, sofern eine verfügbar ist. Die Vorwahl +33 und phoneNumberCountry: "FR" kennzeichnen eine französische Telefonnummer.

finderProvider zeigt den für dieses Ergebnis gemeldeten Finder. Die Zeile hat 500 Credits verbraucht, und error: null bedeutet, dass die API keinen Fehler auf Zeilenebene zurückgegeben hat.

Geprüfte Anrufliste für den Vertrieb erstellen

Sobald phone_results verfügbar ist, kannst Du eine lokale Liste zur Prüfung durch das Vertriebsteam erstellen. Füge den folgenden Block nach der Ergebnisausgabe in derselben Datei ein. Er verwendet die vorhandenen Ergebnisse und löst keinen zweiten API Call aus:

python
results_by_id = {
result["inputId"]: result
for result in phone_results
}
call_list = []
for prospect in prospects:
result = results_by_id.get(prospect["prospect_id"])
if not result or result["status"] != "success":
continue
phone_number = result.get("outputs", {}).get("phoneNumber")
if not phone_number:
continue
call_list_record = prospect.copy()
call_list_record["result"] = result
call_list.append(call_list_record)
print(json.dumps(call_list, indent=2, ensure_ascii=False))

Der Ergebnisindex verwendet inputId als Join Key. Dadurch bleibt jedes Ergebnis mit seinem Quelldatensatz verknüpft, ohne von der Position in der Liste abhängig zu sein. Der API Payload enthält die ID und Profil-URL jedes Prospects, während die ursprüngliche Liste prospects den Namen und Account Owner für die Anrufliste aufbewahrt.

Bei Florians Zeile verknüpft prospect-florian-poullin das zurückgegebene Ergebnis mit den ursprünglichen Werten name, linkedin_url und account_owner. Das Team liest die Telefonnummer und den Ländercode FR aus result.outputs aus. Das vollständige API-Objekt mit Status, Credits und Fehler bleibt unter result angehängt.

Die Schleife für die Anrufliste folgt der Reihenfolge von prospects. Sie kopiert jeden aufgenommenen Prospect, bevor sie result anhängt. Dadurch bleibt die ursprüngliche Quellliste für Korrekturen oder einen anderen Follow-up-Kanal verfügbar.

Eine Zeile ohne Ergebnis, mit Fehler oder ohne Telefonnummer bleibt in der unveränderten Liste prospects, wird aber nicht in call_list aufgenommen. Der Code erstellt damit eine lokale Anrufliste für die anschließende Prüfung.

Kosten der Waterfall Phone Finder API berechnen

Jede neue, nicht aus dem Cache stammende Telefonnummer, die von der standardmäßigen Managed Waterfall gefunden wird, kostet 500 Credits. Ein akzeptiertes Cache-Ergebnis kostet 0 Credits, eine Suche ohne Ergebnis ebenfalls. Prüfe creditsUsed in jeder zurückgegebenen Zeile, um die tatsächlichen Kosten zu ermitteln, statt jedes übermittelte Profil pauschal mit 500 zu multiplizieren.

Nutze für Deine Planung diese Formel:

neu gefundene Telefonnummern ohne Cache × 500 Credits

Vierzig neue Nummern kosten 20.000 Credits. Einhundert neue Nummern kosten 50.000 Credits. Beim aktuellen Basispreis für USD-Aufladungen erhältst Du für 20 US-Dollar 20.000 Credits; 500 Credits entsprechen also 0,50 US-Dollar. Das Growth-Abo, das den REST-API-Zugriff enthält, wird separat berechnet. Aktuelle Pläne und Credit-Pakete findest Du auf der Seite Datablist Preise.

Ein Planungsbeispiel: Angenommen, 100 Profile liefern 20 neue Nummern, 5 akzeptierte Nummern aus dem Cache und 75 Suchen ohne Treffer. Abgerechnet werden die 20 neuen Nummern, die Suche verbraucht also 10.000 Credits. Die Anrufliste kann alle 25 gefundenen Nummern enthalten. Trage 20 in den Rechner ein – nicht alle 100 Inputs oder alle 25 gefundenen Nummern. Dieses Beispiel veranschaulicht nur die Kostenberechnung und keine erwartete Erfolgsquote.

Loading pricing…

Häufige Fehler beheben und Tasks wiederherstellen

  • DATABLIST_API_KEY fehlt: Das Skript wird beendet, bevor es eine Anfrage sendet. Exportiere die Variable und führe die Datei erneut aus.
  • Die API lehnt den Key ab: raise_for_status() meldet den HTTP-Fehler. Kopiere den Personal API Key erneut und prüfe, ob er im Header X-API-Key gesendet wird.
  • Die Profil-URL wird nicht unterstützt: Ersetze eine leere, fehlerhafte, zu einem Unternehmen gehörende oder aus Sales Navigator stammende URL durch ein öffentliches Personenprofil mit dem Pfad linkedin.com/in/....
  • Die Credits reichen nicht aus: Prüfe den Kontostand und die verfügbaren Credits, bevor Du weitere Tasks übermittelst.
  • Der Task hat den Status failed oder stopped: Prüfe den Fehler, die verfügbaren Ergebnisse und den Credit-Verbrauch, bevor Du entscheidest, was erneut ausgeführt werden muss.
  • Eine Zeile enthält kein Ergebnis oder einen Fehler: Bewahre den ursprünglichen Prospect für eine Korrektur oder einen anderen Follow-up-Kanal auf. An der Zeile allein lässt sich nicht erkennen, welcher Anbieter, welche Region oder welche Sichtbarkeitsbedingung das Ergebnis verursacht hat.

Falls die POST-Antwort verloren geht, nutze die vor dem Absenden ausgegebene uniqueId. Liste Deine Tasks auf, bevor Du die Anfrage erneut sendest. Ersetze your-api-key in der folgenden Anfrage und suche anschließend den Task, dessen uniqueId mit dem ausgegebenen Wert übereinstimmt:

shell
curl --get "https://api.datablist.com/v1/enrichments/tasks" \
--header "X-API-Key: your-api-key" \
--data-urlencode "enrichmentId=waterfall-phone-finder" \
--data-urlencode "limit=100"

Befindet sich der Task nicht auf der ersten Seite, folge dem nextCursor aus der Antwort der Task-Liste. Kopiere die @id des passenden Tasks, ersetze unten TASK_ID und prüfe seinen Status oder rufe die vorhandenen Ergebnisse ab:

shell
curl "https://api.datablist.com/v1/enrichments/tasks/TASK_ID" \
--header "X-API-Key: your-api-key"
curl --get "https://api.datablist.com/v1/enrichments/tasks/TASK_ID/results" \
--header "X-API-Key: your-api-key" \
--data-urlencode "limit=100"

Die Task-API-Dokumentation erklärt Task-Status, die Paginierung von Ergebnissen und das Verhalten bei Unterbrechungen.

Nächste Schritte

Du hast jetzt eine wiederverwendbare Requests-Funktion für öffentliche LinkedIn-Profil-URLs und einen Merge über stabile IDs, der gefundene Telefonnummern für die Prüfung durch den Vertrieb aufbereitet.

Ersetze die editierbaren Beispiele durch eine kleine Auswahl qualifizierter Prospects. Behalte ihre stabilen IDs und Account Owner bei und prüfe jede gefundene Nummer, bevor Du die vorbereitete Liste an den Calling-Prozess Deines Teams übergibst. Starte mit einem kleinen Batch, damit Du die ID-Zuordnung und die zurückgegebenen Felder kontrollieren kannst. Wenn Du nicht blockierende Parallelität benötigst, verwende das gepflegte asynchrone HTTPX-Beispiel.