Puede encontrar números de teléfono de LinkedIn con Python enviando URLs públicas de perfiles linkedin.com/in/... a la API Waterfall Phone Finder de Datablist. La API consulta de forma secuencial los proveedores de datos telefónicos disponibles y devuelve los números encontrados en formato internacional, con sus códigos de país.
Esta guía utiliza la librería Requests para crear una integración completa en Python. Después, reutiliza los mismos resultados para preparar una lista local de llamadas comerciales que conserva el nombre, la URL de LinkedIn y el responsable de cuenta de cada prospecto.
📌 Resumen para quienes tienen prisa
Utilice una sola API para encontrar números de teléfono a partir de una lista de URLs públicas de perfiles de LinkedIn. Después, prepare una lista local de llamadas con el nombre y el responsable de cuenta de cada prospecto. Waterfall Phone Finder prueba secuencialmente los proveedores disponibles y deja los números encontrados listos para que su equipo los revise.
- Entrada: Registros de prospectos con una URL pública de perfil de LinkedIn.
- Salida: Una lista local de llamadas con los números internacionales encontrados, sus códigos de país, los nombres y los responsables de cuenta.
💡 ¿Prefiere una solución no-code? Utilice Waterfall Phone Finder de Datablist para encontrar números de teléfono a partir de URLs de perfiles de LinkedIn sin escribir código.
Si parte de nombres en lugar de URLs de perfiles, siga primero el flujo no-code para encontrar teléfonos por nombre o aprenda a encontrar perfiles de LinkedIn por nombre con Python.
Configure Python, Requests y su clave API de Datablist
Para este ejemplo en Python, utilizo el paquete requests. Cree una carpeta para el proyecto, active un entorno virtual, instale Requests y cree el archivo del 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"Cree una Personal API Key en su cuenta de Datablist y úsela como valor de DATABLIST_API_KEY. El acceso a la REST API es una función del plan Growth. Más adelante explico cuántos créditos consumen las búsquedas con resultado.
Encuentre teléfonos con una función completa en Python
El ejemplo utiliza tres registros de prospectos que puede editar. Cada registro incluye un prospect_id estable, un nombre, una URL pública de LinkedIn y el responsable de cuenta encargado de revisar el resultado:
- Florian Poullin en
https://www.linkedin.com/in/florianpoullin/ - Satya Nadella en
https://www.linkedin.com/in/satyanadella/ - Reid Hoffman en
https://www.linkedin.com/in/reidhoffman/
Solo es necesario enviar a la API el ID estable y la URL de LinkedIn. El nombre y el responsable de cuenta permanecen en el registro de origen local. Esta separación reduce el tamaño de la solicitud y conserva los datos comerciales que su equipo necesitará cuando reciba el resultado.
Pegue este script completo en 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))Ejecute el archivo con:
python find_phone_numbers.pyTambién puede descargar el ejemplo síncrono con Requests mantenido por Datablist. El script anterior sigue el mismo orden sencillo: envía una tarea, espera a que termine y recupera todas las páginas de resultados.
Envíe la búsqueda de teléfonos
La comprensión de listas convierte cada prospecto de origen al formato de entrada de la API. Su prospect_id pasa a ser inputId, mientras que linkedin_url se convierte en data.profileUrl. Utilice la URL pública de un perfil personal con la ruta linkedin.com/in/.... Este enrichment no admite URLs de Sales Navigator.
La función genera un uniqueId y lo muestra antes de la solicitud POST. La petición envía ese valor junto con el ID de enrichment waterfall-phone-finder, la configuración de caché y los datos de entrada. Si el envío se completa correctamente, devuelve el estado HTTP 202 Accepted y el @id de una tarea, mientras el procesamiento continúa en segundo plano.
La documentación de la API Waterfall Phone Finder recoge la configuración, los campos de entrada, los resultados, los créditos y los límites vigentes.
Para un prospecto, el cuerpo de la solicitud tiene esta estructura:
{
"enrichmentId": "waterfall-phone-finder",
"uniqueId": "generated-uuid",
"settings": {
"cacheAge": "30"
},
"inputs": [
{
"inputId": "prospect-florian-poullin",
"data": {
"profileUrl": "https://www.linkedin.com/in/florianpoullin/"
}
}
]
}La URL pública del perfil es el dato de entrada de la búsqueda. inputId es la clave de unión que vincula el resultado con el nombre y el responsable de cuenta guardados en su registro de origen. Elija un ID que sea estable en su propio sistema y único dentro de la tarea.
Espere a que termine la tarea en segundo plano
El cliente Requests queda bloqueado localmente mientras consulta el estado de la tarea cada tres segundos. La tarea de Datablist continúa ejecutándose en segundo plano. Cuando su estado cambia a completed, la función pasa a recuperar los resultados. Los estados failed o stopped generan un error con el ID de la tarea para que pueda investigarlo.
Recupere todas las páginas de resultados
La solicitud de resultados recupera hasta 100 filas cada vez. Continúa solicitando páginas hasta que nextCursor sea null. Cada resultado incluye su inputId de origen, por lo que puede vincularlo al prospecto correcto sin depender del orden de la respuesta.
Cómo encuentra un teléfono el waterfall gestionado
El ejemplo establece cacheAge en "30". Datablist comprueba primero si existe un resultado válido con una antigüedad máxima de 30 días. Si lo encuentra, la API puede reutilizarlo. Esta configuración admite el uso de la caché, pero no garantiza que haya una coincidencia.
Si el perfil sigue sin resolverse, el waterfall gestionado prueba secuencialmente los proveedores de datos telefónicos disponibles. Cuando un proveedor no devuelve un número válido, el registro pasa al siguiente. La secuencia se detiene para ese registro en cuanto aparece un número válido.
Ventajas del waterfall en distintos países y mercados
Datablist no depende de un único proveedor de datos telefónicos. Cada proveedor utiliza conjuntos de datos distintos y su cobertura varía según el país y el mercado. Cuando uno no dispone de un número, otro puede encontrarlo. Datablist gestiona todos estos proveedores mediante la misma integración API.
Para un equipo comercial que prepara una lista de llamadas en varios mercados, esto reduce el número de prospectos descartados después de que un único proveedor no encuentre resultados. Su código Python envía una sola tarea y procesa un formato de resultados unificado, por lo que no necesita crear y mantener una integración independiente para cada proveedor.
Establezca cacheAge en "0" cuando su flujo de trabajo necesite solicitar expresamente una búsqueda nueva. Mantenga "30" en este ejemplo para permitir que se reutilice un resultado válido de la caché.
Interprete el resultado completo
Este es uno de los resultados de Florian Poullin. Los números de teléfono aparecen ocultos.
{
"inputId": "prospect-florian-poullin",
"status": "success",
"outputs": {
"finderProvider": "wizleads",
"phoneNumber": "+33 • •• •• •• ••",
"phoneNumberCountry": "FR"
},
"creditsUsed": "500",
"error": null
}phoneNumber contiene el número en formato internacional cuando está disponible. El prefijo +33 y phoneNumberCountry: "FR" indican que se trata de un número francés.
finderProvider identifica el proveedor que encontró este resultado. La fila consumió 500 créditos y error: null indica que la API no devolvió ningún error para ella.
Prepare una lista de llamadas comerciales revisada
Cuando phone_results esté disponible, puede preparar una lista local para que la revise el equipo comercial. Añada este bloque después de imprimir los resultados en el mismo archivo. Reutiliza los resultados existentes y no realiza una segunda llamada a la 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))El índice de resultados utiliza inputId como clave de unión. Así, cada resultado permanece vinculado a su registro de origen sin depender de la posición que ocupe en la lista. El payload de la API incluye el ID y la URL de perfil de cada prospecto, mientras que la lista original prospects conserva el nombre y el responsable de cuenta necesarios para la lista de llamadas.
En la fila de Florian, prospect-florian-poullin vincula el resultado devuelto con los valores originales name, linkedin_url y account_owner. El equipo obtiene el teléfono y su código de país FR desde result.outputs. El objeto completo de la API, incluidos el estado, los créditos y el error, permanece adjunto en result.
El bucle de la lista de llamadas mantiene el orden de prospects. Antes de añadir result, crea una copia de cada prospecto incluido. De este modo, la lista de origen original continúa disponible para realizar correcciones o utilizar otro canal de seguimiento.
Las filas sin resultados, con errores o sin teléfono permanecen en la lista prospects sin modificar, pero no se incorporan a call_list. El código prepara así una lista local de llamadas comerciales para su revisión.
Calcule el coste de la API Waterfall Phone Finder
Cada número de teléfono nuevo que no procede de la caché y que encuentra el waterfall gestionado predeterminado consume 500 créditos. Un resultado aceptado de la caché consume 0 créditos, al igual que una búsqueda sin resultados. Consulte creditsUsed en cada fila devuelta para conocer el consumo real, en lugar de multiplicar por 500 todos los perfiles enviados.
Para hacer una estimación, utilice esta fórmula:
nuevos números encontrados sin caché × 500 créditos
Cuarenta números nuevos consumen 20.000 créditos. Cien números nuevos consumen 50.000 créditos. Con la tarifa base actual de recarga en USD, 20 USD compran 20.000 créditos, por lo que 500 créditos equivalen a 0,50 USD. La suscripción Growth que proporciona acceso a la REST API se factura por separado. Consulte los precios de Datablist para conocer los planes y paquetes de créditos vigentes.
Como ejemplo de planificación, suponga que 100 perfiles generan 20 números nuevos, 5 números aceptados de la caché y 75 búsquedas sin resultados. La cantidad facturable corresponde a los 20 números nuevos, por lo que la búsqueda consume 10.000 créditos. La lista de llamadas puede incluir los 25 números encontrados. Introduzca 20 en la calculadora, no los 100 registros de entrada ni los 25 números encontrados. Este ejemplo explica el cálculo de la facturación, no representa una tasa de éxito prevista.
Solucione errores y recupere una tarea existente
- Falta
DATABLIST_API_KEY: el script se detiene antes de realizar una solicitud. Exporte la variable y vuelva a ejecutar el archivo. - La API rechaza la clave:
raise_for_status()muestra el error HTTP. Vuelva a copiar la Personal API Key y confirme que la solicitud la envía en el headerX-API-Key. - La URL del perfil no es compatible: sustituya cualquier URL vacía, mal formada, de empresa o de Sales Navigator por la URL pública de un perfil personal con la ruta
linkedin.com/in/.... - No hay suficientes créditos: compruebe el saldo de la cuenta y los créditos disponibles antes de enviar más tareas.
- La tarea tiene el estado
failedostopped: revise el error, los resultados disponibles y los créditos consumidos antes de decidir qué debe volver a ejecutar. - Una fila no tiene resultados o contiene un error: conserve el prospecto de origen para corregirlo o utilizar otro canal de seguimiento. La fila por sí sola no permite saber qué proveedor, mercado o condición de visibilidad provocó ese resultado.
Si pierde la respuesta de la solicitud POST, utilice el uniqueId mostrado antes del envío. Consulte sus tareas antes de volver a enviarla. Sustituya your-api-key en esta solicitud y busque la tarea cuyo uniqueId coincida con el valor mostrado:
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 tarea no aparece en la primera página, siga el valor nextCursor de la respuesta con la lista de tareas. Copie el @id de la tarea correspondiente, sustituya TASK_ID a continuación y consulte su estado o recupere los resultados existentes:
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 documentación de la API de tareas explica los estados de las tareas, la paginación de resultados y el comportamiento de las interrupciones.
Próximos pasos
Ahora dispone de una función reutilizable de Requests para URLs públicas de perfiles de LinkedIn y de una combinación mediante IDs estables que prepara los teléfonos encontrados para que el equipo comercial los revise.
Sustituya los ejemplos editables por un pequeño conjunto de prospectos cualificados. Conserve sus IDs estables y sus responsables de cuenta, y revise cada número encontrado antes de enviar la lista preparada al proceso de llamadas de su equipo. Empiece con un lote pequeño para comprobar la correspondencia de los IDs y los campos devueltos. Si necesita concurrencia no bloqueante, utilice el ejemplo asíncrono con HTTPX mantenido por Datablist.


