Puoi trovare numeri di telefono da LinkedIn con Python inviando gli URL pubblici dei profili linkedin.com/in/... alla Waterfall Phone Finder API di Datablist. L’API interroga in sequenza i provider di dati telefonici idonei e restituisce i numeri trovati in formato internazionale, con il relativo prefisso nazionale.
Questa guida utilizza la libreria Requests per realizzare un’integrazione Python completa. In seguito, riutilizza gli stessi risultati per preparare una lista locale di contatti da chiamare, mantenendo il nome, l’URL LinkedIn e l’account owner di ogni prospect.
📌 Riepilogo per chi ha poco tempo
Usa un’unica API per trovare numeri di telefono a partire da una lista di URL pubblici di profili LinkedIn, quindi prepara una lista locale di contatti da chiamare con il nome e l’account owner di ogni prospect. Waterfall Phone Finder prova in sequenza i provider idonei e rende i numeri trovati disponibili per la verifica da parte del tuo team.
- Input: record di prospect con l’URL pubblico del profilo LinkedIn.
- Output: una lista locale di chiamata con numeri di telefono internazionali trovati, codici paese, nomi e account owner.
💡 Preferisci una soluzione no-code? Usa Waterfall Phone Finder di Datablist per trovare numeri di telefono dagli URL dei profili LinkedIn senza scrivere codice.
Se parti dai nomi anziché dagli URL dei profili, segui prima il workflow no-code dal nome al numero di telefono oppure trova i profili LinkedIn dai nomi con Python.
Configurare Python, Requests e la chiave API Datablist
Per questo esempio Python utilizzo il pacchetto requests. Crea una cartella per il progetto, attiva un ambiente virtuale, installa Requests e crea il file dello script:
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"Crea una Personal API Key nel tuo account Datablist e usala per DATABLIST_API_KEY. L’accesso alla REST API è una funzionalità del piano Growth. Più avanti nella guida vedremo quanti crediti vengono utilizzati dalle ricerche riuscite.
Trovare numeri di telefono con una funzione Python
L’esempio utilizza tre record di prospect modificabili. Ogni record contiene un prospect_id stabile, un nome, un URL LinkedIn pubblico e l’account owner incaricato di verificare il risultato:
- Florian Poullin:
https://www.linkedin.com/in/florianpoullin/ - Satya Nadella:
https://www.linkedin.com/in/satyanadella/ - Reid Hoffman:
https://www.linkedin.com/in/reidhoffman/
Solo l’ID stabile e l’URL LinkedIn devono essere inviati all’API. Il nome e l’account owner restano nel record sorgente locale. Questa separazione mantiene leggera la richiesta di ricerca e conserva i dati di business necessari al team dopo la restituzione del risultato.
Incolla questo script completo in find_phone_numbers.py:
import json
import os
import time
import uuid
import requests
def find_phone_numbers(prospects, api_key, settings):
"""Invia un task di ricerca, attende e restituisce tutti i risultati."""
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("Imposta DATABLIST_API_KEY prima di eseguire lo 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))Esegui il file con:
python find_phone_numbers.pyPuoi anche scaricare l’esempio sincrono con Requests mantenuto da Datablist. Lo script precedente segue la stessa semplice sequenza: invia un task, attendi che termini e recupera tutte le pagine dei risultati.
Inviare la ricerca del numero di telefono
La list comprehension trasforma ogni prospect sorgente nel formato di input richiesto dall’API. Il tuo prospect_id diventa inputId, mentre linkedin_url diventa data.profileUrl. Usa l’URL pubblico di un profilo personale con il percorso linkedin.com/in/.... Gli URL di Sales Navigator non sono supportati da questo enrichment.
La funzione genera un uniqueId e lo stampa prima della richiesta POST. La richiesta invia questo valore insieme all’ID dell’enrichment waterfall-phone-finder, all’impostazione della cache e agli input. Se l’invio va a buon fine, restituisce lo stato HTTP 202 Accepted e l’@id del task, mentre l’elaborazione prosegue in background.
La documentazione API di Waterfall Phone Finder elenca le impostazioni, i campi di input, gli output, i crediti e i limiti attuali.
Per un singolo prospect, il corpo della richiesta ha questa struttura:
{
"enrichmentId": "waterfall-phone-finder",
"uniqueId": "generated-uuid",
"settings": {
"cacheAge": "30"
},
"inputs": [
{
"inputId": "prospect-florian-poullin",
"data": {
"profileUrl": "https://www.linkedin.com/in/florianpoullin/"
}
}
]
}L’URL pubblico del profilo è l’input della ricerca. inputId è la chiave di join che collega il risultato al nome e all’account owner presenti nel record sorgente. Scegli un ID stabile nel tuo sistema e univoco all’interno del task.
Attendere il task in background
Il client Requests resta in attesa in locale mentre controlla il task ogni tre secondi. Il task Datablist continua comunque a essere eseguito in background. Quando il suo stato diventa completed, la funzione passa al recupero dei risultati. Uno stato failed o stopped genera un errore con l’ID del task, così da poterlo esaminare.
Recuperare tutte le pagine dei risultati
La richiesta dei risultati recupera fino a 100 righe alla volta. Continua a caricare le pagine finché nextCursor non diventa null. Ogni risultato include il proprio inputId sorgente, quindi puoi associarlo al prospect corretto senza dipendere dall’ordine della risposta.
Come il waterfall gestito trova un numero di telefono
L’esempio imposta cacheAge su "30". Datablist verifica innanzitutto se esiste un risultato idoneo risalente a non più di 30 giorni prima. Se lo trova, l’API può riutilizzarlo. L’impostazione consente di usare un risultato in cache, ma non ne garantisce la disponibilità.
Se il profilo non viene risolto, il waterfall gestito prova in sequenza i provider di dati telefonici idonei. Quando un provider non restituisce un numero utilizzabile, il record passa al successivo. Un numero valido interrompe la sequenza per quel record.
Perché un waterfall funziona in più Paesi e mercati
Datablist non dipende da un solo provider di dati telefonici. I provider utilizzano dataset diversi e la loro copertura varia a seconda del Paese e del mercato. Se uno non dispone di un numero di telefono, un altro potrebbe trovarlo. Datablist gestisce tutti questi provider attraverso la stessa integrazione API.
Per un team sales che crea una lista di chiamata su più mercati, questo significa escludere meno prospect dopo il mancato risultato di un singolo provider. Il codice Python invia un unico task e legge un solo formato di risultato, quindi non devi creare e mantenere un’integrazione separata per ciascun provider.
Imposta cacheAge su "0" quando il workflow richiede espressamente una nuova ricerca. Nell’esempio mantieni "30", così da poter riutilizzare un eventuale risultato idoneo presente in cache.
Leggere il risultato completo
Ecco un risultato per Florian Poullin. I numeri di telefono sono stati mascherati.
{
"inputId": "prospect-florian-poullin",
"status": "success",
"outputs": {
"finderProvider": "wizleads",
"phoneNumber": "+33 • •• •• •• ••",
"phoneNumberCountry": "FR"
},
"creditsUsed": "500",
"error": null
}phoneNumber contiene il numero internazionale, quando disponibile. Il prefisso +33 e phoneNumberCountry: "FR" indicano un numero francese.
finderProvider indica il finder che ha restituito questo risultato. La riga ha utilizzato 500 crediti e error: null significa che l’API non ha restituito errori a livello di riga.
Preparare una lista di chiamata verificata
Quando phone_results è disponibile, puoi preparare una lista locale che il team sales potrà verificare. Aggiungi questo blocco dopo la stampa dei risultati nello stesso file. Riutilizza i risultati esistenti e non effettua una seconda chiamata API:
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))L’indice dei risultati usa inputId come chiave di join, così ogni risultato rimane associato al record sorgente senza dipendere dalla posizione nella lista. Il payload dell’API contiene l’ID e l’URL del profilo di ogni prospect, mentre la lista originale prospects conserva il nome e l’account owner necessari per la lista di chiamata.
Per la riga di Florian, prospect-florian-poullin collega il risultato restituito ai valori originali name, linkedin_url e account_owner. Il team legge il numero e il codice paese FR da result.outputs. L’oggetto API completo, inclusi stato, crediti ed errore, rimane disponibile in result.
Il ciclo della lista di chiamata segue l’ordine di prospects. Copia ogni prospect incluso prima di aggiungere result, lasciando così invariata la lista sorgente originale per eventuali correzioni o per un altro canale di follow-up.
Una riga senza risultato, con un errore o con il numero vuoto resta nella lista prospects invariata, ma non viene inserita in call_list. Il codice prepara così una lista locale di contatti da chiamare e verificare.
Stimare i costi della Waterfall Phone Finder API
Ogni nuovo numero di telefono non presente in cache e trovato dal waterfall gestito predefinito utilizza 500 crediti. Un risultato accettato dalla cache utilizza 0 crediti, così come una ricerca senza risultati. Per conoscere la spesa effettiva, leggi creditsUsed in ogni riga restituita invece di moltiplicare per 500 tutti i profili inviati.
Per una stima, usa questa formula:
nuovi numeri di telefono trovati fuori dalla cache × 500 crediti
Quaranta nuovi numeri utilizzano 20.000 crediti. Cento nuovi numeri ne utilizzano 50.000. Con l’attuale tariffa base di ricarica in USD, 20 $ acquistano 20.000 crediti, quindi 500 crediti valgono 0,50 $. L’abbonamento Growth che offre l’accesso alla REST API è separato. Consulta i prezzi di Datablist per conoscere i piani e i pacchetti di crediti attuali.
Come esempio di pianificazione, supponiamo che 100 profili producano 20 nuovi numeri, 5 numeri accettati dalla cache e 75 ricerche senza risultato. La quantità fatturabile corrisponde ai 20 numeri nuovi, quindi la ricerca utilizza 10.000 crediti. La lista di chiamata può includere tutti e 25 i numeri trovati. Inserisci 20 nel calcolatore, non tutti i 100 input né tutti i 25 numeri trovati. Questo esempio illustra il calcolo dei costi, non un tasso di successo previsto.
Risolvere gli errori e recuperare un task esistente
DATABLIST_API_KEYnon è presente: lo script si interrompe prima di effettuare una richiesta. Esporta la variabile ed esegui nuovamente il file.- L’API rifiuta la chiave:
raise_for_status()segnala l’errore HTTP. Copia di nuovo la Personal API Key e verifica che la richiesta la invii nell’headerX-API-Key. - L’URL del profilo non è supportato: sostituisci un URL vuoto, non valido, aziendale o di Sales Navigator con un profilo personale pubblico che utilizzi il percorso
linkedin.com/in/.... - I crediti non sono sufficienti: controlla il saldo dell’account e i crediti disponibili prima di inviare altri task.
- Il task è
failedostopped: esamina l’errore, i risultati disponibili e i crediti utilizzati prima di decidere quali operazioni debbano ancora essere eseguite. - Una riga non ha risultati o contiene un errore: conserva il prospect sorgente per correggerlo o contattarlo tramite un altro canale. La riga, da sola, non indica quale provider, area geografica o condizione di visibilità abbia determinato l’esito.
Se perdi la risposta alla richiesta POST, usa l’uniqueId stampato prima dell’invio. Elenca i tuoi task prima di inviare nuovamente la richiesta. Sostituisci your-api-key in questa richiesta, quindi individua il task il cui uniqueId corrisponde al valore stampato:
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"Se il task non compare nella prima pagina, segui il valore nextCursor presente nella risposta dell’elenco dei task. Copia l’@id del task corrispondente, sostituisci TASK_ID qui sotto e controllane lo stato oppure recupera i risultati esistenti:
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"La documentazione della task API spiega gli stati dei task, la paginazione dei risultati e il comportamento in caso di interruzione.
Prossimi passi
Ora hai una funzione Requests riutilizzabile per gli URL pubblici dei profili LinkedIn e un merge basato su ID stabili che prepara i numeri trovati per la verifica da parte del team sales.
Sostituisci gli esempi modificabili con un piccolo gruppo di prospect qualificati. Mantieni i loro ID stabili e gli account owner, quindi verifica ogni numero trovato prima di passare la lista preparata al processo di chiamata del tuo team. Inizia con un batch ridotto, così potrai controllare l’associazione degli ID e i campi restituiti. Se ti serve una gestione concorrente non bloccante, usa l’esempio asincrono con HTTPX mantenuto da Datablist.


