Vous pouvez trouver des numéros de téléphone LinkedIn avec Python en envoyant des URL publiques de profils linkedin.com/in/... à l’API Waterfall Phone Finder de Datablist. L’API interroge successivement les fournisseurs de données téléphoniques éligibles et renvoie les numéros trouvés au format international, avec leur indicatif pays.
Ce guide s’appuie sur la bibliothèque Requests pour réaliser une intégration Python complète. Nous réutiliserons ensuite les mêmes résultats afin de préparer une liste d’appels commerciale locale contenant le nom, l’URL LinkedIn et l’account owner de chaque prospect.
📌 L’essentiel pour aller vite
Utilisez une seule API pour trouver des numéros de téléphone à partir d’une liste d’URL publiques de profils LinkedIn, puis préparez une liste d’appels locale avec le nom et l’account owner de chaque prospect. Waterfall Phone Finder teste successivement les fournisseurs éligibles et conserve les numéros trouvés pour validation par votre équipe.
- Entrée : fiches de prospects comportant l’URL publique d’un profil LinkedIn.
- Sortie : liste d’appels locale avec les numéros internationaux trouvés, leur code pays, les noms et les account owners.
💡 Vous préférez une solution no-code ? Utilisez le Waterfall Phone Finder de Datablist pour trouver des numéros à partir d’URL de profils LinkedIn sans écrire de code.
Si vous disposez de noms plutôt que d’URL de profils, suivez d’abord le workflow no-code pour passer d’un nom à un numéro ou apprenez à trouver des profils LinkedIn à partir de noms avec Python.
Configurer Python, Requests et votre clé API Datablist
Pour cet exemple Python, j’utilise le package requests. Créez un dossier de projet, activez un environnement virtuel, installez Requests et créez le fichier du 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"Créez une Personal API Key dans votre compte Datablist et utilisez-la comme valeur de DATABLIST_API_KEY. L’accès à la REST API est inclus dans l’offre Growth. Nous verrons plus loin combien de crédits consomment les recherches fructueuses.
Trouver des numéros avec une fonction Python complète
L’exemple utilise trois fiches de prospects modifiables. Chacune contient un prospect_id stable, un nom, une URL LinkedIn publique et l’account owner chargé de valider le résultat :
- Florian Poullin sur
https://www.linkedin.com/in/florianpoullin/ - Satya Nadella sur
https://www.linkedin.com/in/satyanadella/ - Reid Hoffman sur
https://www.linkedin.com/in/reidhoffman/
Seuls l’identifiant stable et l’URL LinkedIn doivent être transmis à l’API. Le nom et l’account owner restent dans votre fiche source locale. Cette séparation allège la requête tout en préservant les informations métier dont votre équipe aura besoin une fois le résultat obtenu.
Collez ce script complet dans find_phone_numbers.py :
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))Exécutez le fichier avec :
python find_phone_numbers.pyVous pouvez également télécharger l’exemple synchrone avec Requests maintenu par Datablist. Le script ci-dessus suit le même enchaînement simple : soumettre une tâche, attendre son exécution, puis récupérer toutes les pages de résultats.
Envoyer la recherche de numéro
La compréhension de liste convertit chaque prospect source au format d’entrée attendu par l’API. Votre prospect_id devient inputId, tandis que linkedin_url devient data.profileUrl. Utilisez l’URL publique d’un profil personnel suivant le chemin linkedin.com/in/.... Les URL Sales Navigator ne sont pas prises en charge par cet enrichissement.
La fonction génère un uniqueId et l’affiche avant la requête POST. La requête transmet cette valeur avec l’identifiant d’enrichissement waterfall-phone-finder, le réglage du cache et les entrées. Une soumission réussie renvoie le statut HTTP 202 Accepted et l’@id d’une tâche, dont le traitement se poursuit en arrière-plan.
La documentation de l’API Waterfall Phone Finder répertorie les réglages, champs d’entrée, sorties, crédits et limites en vigueur.
Pour un prospect, le corps de la requête suit cette structure :
{
"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 publique du profil constitue l’entrée de la recherche. inputId est la clé de jointure qui relie le résultat au nom et à l’account owner de votre fiche source. Choisissez un identifiant stable dans votre propre système et unique au sein de la tâche.
Attendre la fin de la tâche en arrière-plan
Le client Requests reste bloqué localement pendant qu’il vérifie l’état de la tâche toutes les trois secondes. La tâche Datablist, elle, continue de s’exécuter en arrière-plan. Dès que son statut passe à completed, la fonction récupère les résultats. Un statut failed ou stopped déclenche une erreur contenant l’identifiant de la tâche afin que vous puissiez l’examiner.
Récupérer toutes les pages de résultats
La requête de résultats demande jusqu’à 100 lignes à la fois. Elle continue à charger les pages jusqu’à ce que nextCursor vaille null. Chaque résultat contient son inputId source : vous pouvez ainsi le rattacher au bon prospect sans dépendre de l’ordre de la réponse.
Comment le waterfall géré trouve un numéro
Dans cet exemple, cacheAge est défini sur "30". Datablist commence par rechercher un résultat éligible datant de 30 jours au maximum. S’il en existe un, l’API peut le réutiliser. Ce réglage autorise l’utilisation du cache, sans garantir qu’un résultat y sera disponible.
Si aucun résultat n’est encore associé au profil, le waterfall géré interroge successivement les fournisseurs de données téléphoniques éligibles. Lorsqu’un fournisseur ne renvoie aucun numéro exploitable, la recherche se poursuit auprès du suivant. Dès qu’un numéro exploitable est trouvé, la séquence s’arrête pour cette fiche.
Pourquoi un waterfall améliore la couverture internationale
Datablist ne dépend pas d’un seul fournisseur de données téléphoniques. Chaque fournisseur utilise des sources différentes, et sa couverture varie selon les pays et les marchés. Si l’un ne possède aucun numéro, un autre peut le trouver. Datablist orchestre tous ces fournisseurs au sein d’une même intégration API.
Pour une équipe commerciale qui constitue une liste d’appels sur plusieurs marchés, cela réduit le nombre de prospects écartés après l’échec d’un seul fournisseur. Votre code Python soumet une tâche unique et lit un format de résultat commun : inutile de développer et de maintenir une intégration distincte pour chaque fournisseur.
Définissez cacheAge sur "0" lorsque votre workflow exige spécifiquement une nouvelle recherche. Conservez "30" dans cet exemple afin de permettre la réutilisation d’un résultat éligible présent dans le cache.
Lire le résultat complet
Voici un résultat obtenu pour Florian Poullin. Les numéros de téléphone sont masqués ci-dessous.
{
"inputId": "prospect-florian-poullin",
"status": "success",
"outputs": {
"finderProvider": "wizleads",
"phoneNumber": "+33 • •• •• •• ••",
"phoneNumberCountry": "FR"
},
"creditsUsed": "500",
"error": null
}phoneNumber contient le numéro au format international lorsqu’il est disponible. Le préfixe +33 et la valeur phoneNumberCountry: "FR" indiquent qu’il s’agit d’un numéro français.
finderProvider correspond au fournisseur indiqué pour ce résultat. La ligne a consommé 500 crédits, tandis que error: null signifie que l’API n’a renvoyé aucune erreur pour cette ligne.
Préparer une liste d’appels commerciale validée
Une fois phone_results disponible, vous pouvez préparer une liste locale que l’équipe commerciale pourra valider. Ajoutez ce bloc après l’affichage des résultats dans le même fichier. Il réutilise les résultats existants et ne déclenche aucun second appel 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’index des résultats utilise inputId comme clé de jointure. Chaque résultat reste donc lié à sa fiche source sans dépendre de sa position dans la liste. Le payload de l’API contient l’identifiant et l’URL de profil de chaque prospect, tandis que la liste prospects d’origine conserve son nom et son account owner, nécessaires à la liste d’appels.
Pour la ligne de Florian, prospect-florian-poullin relie le résultat aux valeurs name, linkedin_url et account_owner d’origine. L’équipe trouve le numéro et son code pays FR dans result.outputs. L’objet API complet, avec son statut, ses crédits et son éventuelle erreur, reste associé sous result.
La boucle de création de la liste d’appels respecte l’ordre de prospects. Elle copie chaque prospect retenu avant d’y associer result, ce qui laisse la liste source intacte pour d’éventuelles corrections ou pour un autre canal de suivi.
Une ligne sans résultat, en erreur ou sans numéro reste dans la liste prospects inchangée, mais n’est pas ajoutée à call_list. Le code prépare ainsi une liste d’appels commerciale locale à valider.
Estimer le coût de l’API Waterfall Phone Finder
Chaque nouveau numéro hors cache trouvé par le waterfall géré par défaut consomme 500 crédits. Un résultat accepté depuis le cache consomme 0 crédit, tout comme une recherche sans résultat. Pour connaître la dépense réelle, consultez la valeur creditsUsed de chaque ligne renvoyée au lieu de multiplier tous les profils soumis par 500.
Pour vos estimations, utilisez cette formule :
nouveaux numéros hors cache trouvés × 500 crédits
Quarante nouveaux numéros consomment 20 000 crédits. Cent nouveaux numéros en consomment 50 000. Au tarif de recharge de base actuel en dollars, 20 $ permettent d’acheter 20 000 crédits : 500 crédits valent donc 0,50 $. L’abonnement Growth donnant accès à la REST API est facturé séparément. Consultez les tarifs Datablist pour connaître les offres et packs de crédits actuels.
Prenons un exemple de prévision : sur 100 profils, vous obtenez 20 nouveaux numéros, 5 numéros acceptés depuis le cache et 75 recherches sans résultat. Seuls les 20 nouveaux numéros sont facturables, soit 10 000 crédits. La liste d’appels peut contenir les 25 numéros trouvés. Saisissez 20 dans le calculateur, et non les 100 entrées ou les 25 numéros obtenus. Cet exemple illustre le mode de calcul de la facturation, pas un taux de réussite attendu.
Corriger les erreurs et récupérer une tâche existante
DATABLIST_API_KEYest absente : le script s’arrête avant d’effectuer une requête. Exportez la variable, puis relancez le fichier.- L’API refuse la clé :
raise_for_status()signale l’erreur HTTP. Copiez à nouveau la Personal API Key et vérifiez que la requête la transmet dans le headerX-API-Key. - L’URL du profil n’est pas prise en charge : remplacez toute URL vide, incorrecte, associée à une entreprise ou issue de Sales Navigator par l’URL publique d’un profil personnel suivant le chemin
linkedin.com/in/.... - Le solde de crédits est insuffisant : vérifiez le solde du compte et les crédits disponibles avant d’envoyer de nouvelles tâches.
- Le statut de la tâche est
failedoustopped: examinez son erreur, les résultats disponibles et les crédits consommés avant de décider quelles recherches doivent encore être exécutées. - Une ligne ne contient aucun résultat ou présente une erreur : conservez le prospect source pour le corriger ou le contacter par un autre canal. La ligne seule ne permet pas de savoir quel fournisseur, quelle zone géographique ou quelle condition de visibilité a provoqué ce résultat.
Si vous perdez la réponse à la requête POST, utilisez l’uniqueId affiché avant l’envoi. Listez vos tâches avant d’en soumettre une nouvelle. Remplacez your-api-key dans cette requête, puis recherchez la tâche dont l’uniqueId correspond à la valeur affichée :
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"Si la tâche ne figure pas sur la première page, utilisez le nextCursor renvoyé par la liste des tâches. Copiez l’@id de la tâche correspondante, remplacez TASK_ID ci-dessous, puis vérifiez son statut ou récupérez ses résultats existants :
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 documentation de l’API des tâches explique les différents statuts, la pagination des résultats et le comportement en cas d’interruption.
Prochaines étapes
Vous disposez désormais d’une fonction Requests réutilisable pour les URL publiques de profils LinkedIn et d’une jointure fondée sur des identifiants stables, capable de préparer les numéros trouvés pour validation par l’équipe commerciale.
Remplacez les exemples modifiables par un petit groupe de prospects qualifiés. Conservez leurs identifiants stables et leurs account owners, puis validez chaque numéro trouvé avant de transmettre la liste au processus d’appels de votre équipe. Commencez par un petit lot afin de vérifier la correspondance des identifiants et les champs renvoyés. Si vous avez besoin d’une exécution concurrente non bloquante, utilisez l’exemple asynchrone avec HTTPX maintenu par Datablist.


