Je kunt met Python telefoonnummers van LinkedIn vinden door openbare linkedin.com/in/...-profiel-URL's naar de Waterfall Phone Finder API van Datablist te sturen. De API controleert achtereenvolgens geschikte databronnen voor telefoonnummers en retourneert gevonden nummers in internationaal formaat, inclusief landcode.

In deze handleiding gebruiken we de Requests-library voor één complete Python-integratie. Daarna hergebruiken we dezelfde resultaten om een lokale bellijst voor sales te maken, met voor elke prospect de naam, LinkedIn-URL en account owner.

📌 Samenvatting voor wie weinig tijd heeft

Gebruik één API om telefoonnummers te vinden op basis van een lijst met openbare LinkedIn-profiel-URL's. Maak vervolgens een lokale bellijst met de naam en account owner van elke prospect. De Waterfall Phone Finder probeert achtereenvolgens geschikte providers en zet gevonden nummers klaar voor controle door je team.

  • Input: Prospectgegevens met een openbare LinkedIn-profiel-URL.
  • Output: Een lokale bellijst met gevonden internationale telefoonnummers, landcodes, namen en account owners.

💡 Liever een no-code oplossing? Gebruik Datablist's Waterfall Phone Finder om telefoonnummers te vinden via LinkedIn-profiel-URL's zonder code te schrijven.

Begin je met namen in plaats van profiel-URL's? Volg dan eerst de no-code workflow van naam naar telefoonnummer of zoek LinkedIn-profielen op naam met Python.

Python, Requests en je Datablist API-key instellen

Voor dit Python-voorbeeld gebruik ik het requests-package. Maak een projectmap, activeer een virtual environment, installeer Requests en maak het scriptbestand aan:

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"

Maak in je Datablist-account een Personal API Key aan en gebruik deze voor DATABLIST_API_KEY. Toegang tot de REST API is onderdeel van het Growth-abonnement. Verderop in deze handleiding lees je hoeveel credits succesvolle zoekopdrachten kosten.

Telefoonnummers vinden met één Python-functie

Het voorbeeld gebruikt drie prospectrecords die je kunt aanpassen. Elk record bevat een vaste prospect_id, een naam, een openbare LinkedIn-URL en de account owner die het resultaat controleert:

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

Alleen de vaste ID en LinkedIn-URL hoeven naar de API te worden gestuurd. De naam en account owner blijven in je lokale bronrecord staan. Zo blijft de lookup-request compact, terwijl je de bedrijfsgegevens bewaart die je team na ontvangst van het resultaat nodig heeft.

Plak dit volledige script in find_phone_numbers.py:

python
import json
import os
import time
import uuid
import requests
def find_phone_numbers(prospects, api_key, settings):
"""Submit one phone lookup task, wait, and return every result."""
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("Set DATABLIST_API_KEY before running this script.")
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))

Voer het bestand uit met:

shell
python find_phone_numbers.py

Je kunt ook het door Datablist onderhouden synchrone Requests-voorbeeld downloaden. Het bovenstaande script volgt dezelfde eenvoudige volgorde: één taak indienen, wachten en alle resultaatpagina's ophalen.

De telefoonzoekopdracht indienen

De list comprehension zet elke prospect uit de bron om naar het inputformaat van de API. Je prospect_id wordt inputId en linkedin_url wordt data.profileUrl. Gebruik een openbare URL van een persoonlijk profiel met het pad linkedin.com/in/.... Sales Navigator-URL's worden niet door deze enrichment ondersteund.

De functie genereert een uniqueId en toont deze vóór de POST-request. De request verstuurt deze waarde samen met de enrichment-ID waterfall-phone-finder, de cache-instelling en de input. Na een geslaagde indiening retourneert de API HTTP 202 Accepted en een taak-@id, waarna de verwerking op de achtergrond doorgaat.

In de API-documentatie van Waterfall Phone Finder vind je de actuele instellingen, inputvelden, output, credits en limieten.

Voor één prospect heeft de request body deze structuur:

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

De openbare profiel-URL is de input voor de lookup. inputId is de sleutel waarmee je het resultaat koppelt aan de naam en account owner in je bronrecord. Kies een ID die in je eigen systeem stabiel en binnen de taak uniek is.

Wachten op de achtergrondtaak

De Requests-client blokkeert lokaal terwijl deze elke drie seconden de taakstatus controleert. De Datablist-taak blijft ondertussen op de achtergrond actief. Zodra de status completed wordt, haalt de functie de resultaten op. Bij de status failed of stopped genereert de functie een fout met de taak-ID, zodat je deze kunt onderzoeken.

Alle resultaatpagina's ophalen

De request vraagt maximaal 100 rijen per keer op. De functie blijft pagina's ophalen totdat nextCursor null is. Elk resultaat bevat de bijbehorende inputId, zodat je het aan de juiste prospect kunt koppelen zonder op de volgorde van de response te vertrouwen.

Zo vindt de managed waterfall een telefoonnummer

In het voorbeeld staat cacheAge op "30". Datablist controleert eerst of er een geschikt resultaat van maximaal 30 dagen oud beschikbaar is. Zo ja, dan kan de API dit hergebruiken. De instelling staat een cache hit toe, maar garandeert deze niet.

Als het profiel niet wordt gevonden, probeert de managed waterfall achtereenvolgens geschikte databronnen voor telefoonnummers. Levert een provider geen bruikbaar nummer op, dan gaat het record door naar de volgende. Zodra een bruikbaar nummer wordt gevonden, stopt de reeks voor dat record.

Waterfall-zoekopdracht die na een leeg resultaat doorgaat en stopt zodra een telefoonnummer is gevonden
Waterfall-zoekopdracht die na een leeg resultaat doorgaat en stopt zodra een telefoonnummer is gevonden

Waarom een waterfall werkt in verschillende landen en markten

Datablist is niet afhankelijk van één provider voor telefoondata. Providers gebruiken verschillende datasets en hun dekking verschilt per land en markt. Als de ene provider geen telefoonnummer heeft, kan een andere het wel vinden. Datablist beheert deze providers via dezelfde API-integratie.

Voor salesteams die een bellijst voor meerdere markten samenstellen, betekent dit dat minder prospects buiten de boot vallen wanneer één provider niets vindt. Je Python-code dient één taak in en verwerkt één resultaatformaat. Je hoeft dus niet voor elke provider een aparte integratie te bouwen en onderhouden.

Stel cacheAge in op "0" wanneer je workflow specifiek een nieuwe lookup nodig heeft. Gebruik voor dit voorbeeld "30", zodat een geschikt gecachet resultaat kan worden hergebruikt.

Het volledige resultaat uitlezen

Hieronder staat één resultaat voor Florian Poullin. De telefoonnummers zijn afgeschermd.

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

phoneNumber bevat het internationale nummer als dit beschikbaar is. Het voorvoegsel +33 en phoneNumberCountry: "FR" geven aan dat het om een Frans nummer gaat.

finderProvider is de finder die voor dit resultaat is vermeld. De rij gebruikte 500 credits en error: null betekent dat de API geen fout op rijniveau retourneerde.

Een gecontroleerde bellijst voor sales maken

Zodra phone_results beschikbaar is, kun je een lokale lijst samenstellen die het salesteam kan controleren. Voeg dit blok na het printen van de resultaten toe aan hetzelfde bestand. Het hergebruikt de bestaande resultaten en doet geen tweede API-call:

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))

De resultatenindex gebruikt inputId als koppelsleutel. Zo blijft elk resultaat verbonden met het juiste bronrecord, ongeacht de positie in de lijst. De API-payload bevat de ID en profiel-URL van elke prospect, terwijl de oorspronkelijke prospects-lijst de naam en account owner voor de bellijst bewaart.

Voor de rij van Florian koppelt prospect-florian-poullin het geretourneerde resultaat aan de oorspronkelijke name, linkedin_url en account_owner. Het team haalt het telefoonnummer en de landcode FR uit result.outputs. Het volledige API-object, inclusief status, credits en eventuele fout, blijft onder result gekoppeld.

De loop voor de bellijst volgt de volgorde van prospects. Elke opgenomen prospect wordt gekopieerd voordat result wordt toegevoegd. Daardoor blijft de oorspronkelijke bronlijst beschikbaar voor correcties of een ander opvolgkanaal.

Een rij zonder resultaat, met een fout of zonder telefoonnummer blijft in de ongewijzigde prospects-lijst staan, maar wordt niet aan call_list toegevoegd. De code maakt zo een lokale bellijst voor controle door sales.

Kosten van de Waterfall Phone Finder API berekenen

Elk nieuw, niet-gecachet telefoonnummer dat de standaard managed waterfall vindt, kost 500 credits. Een geaccepteerd gecachet resultaat kost 0 credits en een zoekopdracht zonder resultaat eveneens. Controleer voor de werkelijke kosten de waarde creditsUsed van elke geretourneerde rij, in plaats van ieder ingediend profiel met 500 te vermenigvuldigen.

Gebruik voor je planning deze formule:

gevonden nieuwe, niet-gecachete telefoonnummers × 500 credits

Veertig nieuwe nummers kosten 20.000 credits. Honderd nieuwe nummers kosten 50.000 credits. Tegen het huidige standaardtarief in Amerikaanse dollars koop je voor $ 20 20.000 credits, dus zijn 500 credits $ 0,50 waard. Het Growth-abonnement dat toegang tot de REST API biedt, staat hier los van. Bekijk Datablist pricing voor actuele abonnementen en creditbundels.

Stel dat 100 profielen 20 nieuwe nummers, 5 geaccepteerde gecachete nummers en 75 zoekopdrachten zonder resultaat opleveren. Alleen de 20 nieuwe nummers zijn factureerbaar, dus de lookup kost 10.000 credits. De bellijst kan alle 25 gevonden nummers bevatten. Vul in de calculator 20 in, niet alle 100 inputrecords of alle 25 gevonden nummers. Dit voorbeeld verduidelijkt de kostenberekening en is geen verwachte success rate.

Loading pricing…

Veelvoorkomende fouten oplossen en een taak herstellen

  • DATABLIST_API_KEY ontbreekt: het script stopt voordat het een request doet. Exporteer de variabele en voer het bestand opnieuw uit.
  • De API weigert de key: raise_for_status() meldt de HTTP-fout. Kopieer de Personal API Key opnieuw en controleer of de request deze in de X-API-Key-header meestuurt.
  • De profiel-URL wordt niet ondersteund: vervang een lege of ongeldige URL, bedrijfs-URL of Sales Navigator-URL door een openbaar persoonlijk profiel met het pad linkedin.com/in/....
  • Onvoldoende credits: controleer het accountsaldo en de beschikbare credits voordat je meer taken indient.
  • De taak heeft de status failed of stopped: controleer de foutmelding, beschikbare resultaten en het creditverbruik voordat je bepaalt wat nogmaals moet worden uitgevoerd.
  • Een rij heeft geen resultaat of bevat een fout: bewaar de prospect uit de bron voor correctie of een ander opvolgkanaal. Uit de rij alleen kun je niet afleiden welke provider, regio of zichtbaarheidsbeperking de uitkomst heeft veroorzaakt.

Als de POST-response verloren gaat, gebruik je de uniqueId die vóór indiening is getoond. Bekijk je taken voordat je opnieuw iets indient. Vervang your-api-key in deze request en zoek vervolgens de taak waarvan de uniqueId overeenkomt met de getoonde waarde:

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"

Staat de taak niet op de eerste pagina? Volg dan de nextCursor uit de response met de takenlijst. Kopieer de @id van de juiste taak, vervang hieronder TASK_ID en controleer de status of haal de bestaande resultaten op:

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"

De documentatie van de task API legt taakstatussen, paginering van resultaten en onderbrekingsgedrag uit.

Volgende stappen

Je hebt nu één herbruikbare Requests-functie voor openbare LinkedIn-profiel-URL's en één koppeling op basis van vaste ID's waarmee je gevonden telefoonnummers klaarzet voor controle door sales.

Vervang de aanpasbare voorbeelden door een kleine groep gekwalificeerde prospects. Behoud hun vaste ID's en account owners en controleer elk gevonden nummer voordat je de voorbereide lijst doorstuurt naar het belproces van je team. Begin met een kleine batch, zodat je de ID-koppeling en geretourneerde velden kunt controleren. Heb je non-blocking concurrency nodig? Gebruik dan het onderhouden async HTTPX-voorbeeld.