Setup prompt
enrich_csv.py, that turns a CSV of LinkedIn profile URLs into a CSV of names, titles, companies and, if you ask for them, work emails. It uses two Forager endpoints: the person lookup (1 credit per row) and the bulk work email lookup (5 credits per address found, one batch for the whole file). It prints the credit estimate and asks before it spends anything, and a second run skips rows that are already in the output file.
What you need
- Python 3.9 or newer and
pip install requests. FORAGER_API_KEYandFORAGER_ACCOUNT_IDin the environment, from the Web App.- A CSV with a
linkedin_urlcolumn. The fictional sample below is what the walkthrough uses.
input.csv
The script
1
Parse the URLs and estimate the cost
The person lookup takes the LinkedIn public identifier, the slug after
/in/. Everything else in the URL (scheme, www, trailing slash, query string) is dropped. Rows that already have an id in the output file are skipped, so a crashed run can be resumed.enrich_csv.py (part 1 of 3)
2
Call the API with retries
One helper sends every request. A
403 stops the run (the key or Account ID is wrong, retrying cannot help), a 429 waits and retries, and anything else is recorded in the row’s error column so one bad row does not stop the file. See errors and rate limits.enrich_csv.py (part 2 of 3)
3
Run the file end to end
The main function prints how many rows are new and what they cost, waits for a
y unless you pass --yes, enriches row by row (appending to the output as it goes), and runs the work email batch last so a crash mid-file never loses the person data already fetched.enrich_csv.py (part 3 of 3)
4
Run it
Output (illustrative)
output.csv (illustrative)
Edge cases the script handles
- A URL that is not a profile URL (a company page, an empty cell) is counted and skipped, never sent.
- A person the lookup cannot resolve gets the status code and body in
errorand the run continues. - Duplicate URLs in the input are collapsed by the bulk endpoint, which charges one lookup for identical rows.
- Not enough credits for the batch: the bulk endpoint rejects the whole batch and charges nothing, so the person data already written is safe. Buy credits, then re-run with
--work-emails; the person lookups are skipped and only the batch runs again. - Resuming: rows with an
idin the output file are skipped. Delete a row from the output to redo it.
Adapt it
- Need phone numbers instead? Replace
bulk_work_emailswith one phone number lookup per row (person_idfrom the person lookup, 15 credits per lookup). There is no bulk phone endpoint. - Thousands of rows? Run the batch in chunks and send a
webhook_urlinstead of polling. See Bulk work email lookup. - Whole datasets are cheaper as a data feed than as API calls.
Related
Python quickstart
The client this script is built on, step by step.
Contact enrichment guide
Every field in the person record.
Credit pricing
What each call costs.
Report bad data
Send back invalid addresses with the feedback endpoints.