Data catalog · Proxycurl Migration

Proxycurl Person Lookup (email) replacement

Proxycurl resolved an email address to a person in one request. RichAPI does it in two: POST /find_linkedin_url_by_email returns the profile URL, then POST /enrich_profile turns that into the record. Two calls, two charges, and both of them bill on a 2xx even when the answer is empty. Price the chain, not the call.

Try this live — 25 free credits

Last updated September 22, 2026

One Proxycurl call becomes two calls here

Proxycurl's Person Lookup took an email address and gave you back a person. The replacement is a chain: `POST /find_linkedin_url_by_email` resolves the address to a LinkedIn profile URL, then `POST /enrich_profile` turns that URL into the record. **[Get 25 free credits — no card](https://app.richapi.ai)** Two calls means two charges. Everything on this page prices the chain rather than the call, because a per-call number would understate what your job actually spends.

The before and after

```bash # Before (Proxycurl) — dead, one request # GET https://nubela.co/proxycurl/api/linkedin/profile/resolve/email?email=<addr> # -H "Authorization: Bearer $PROXYCURL_KEY" # # After (RichAPI), call 1 of 2 — email to profile URL curl -X POST https://api.richapi.ai/api/v1/find_linkedin_url_by_email \ -H "x-api-key: $RICHAPI_KEY" \ -H "Content-Type: application/json" \ -d '{"email": "jane@acme.com"}' # After (RichAPI), call 2 of 2 — profile URL to person record curl -X POST https://api.richapi.ai/api/v1/enrich_profile \ -H "x-api-key: $RICHAPI_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://www.linkedin.com/in/example/"}' ``` The `email` field is validated against an email pattern, so a malformed address fails as a 4xx and costs nothing. That is worth using: filter obvious garbage before the call and the API will reject the rest for free.

Read the first response carefully

The lookup returns a wrapper, not a flat object: ```json { "status": "...", "data": { "LinkedIn Profile URL": "https://www.linkedin.com/in/example/" } } ``` That key is the literal string `LinkedIn Profile URL`, spaces and capitals included. It is not `linkedin_url`, and your JSON parser will not guess it for you. In TypeScript that means bracket access, `body.data["LinkedIn Profile URL"]`, and in a typed client it means an explicit alias in the model rather than a snake-case convention. Getting this wrong produces `undefined` flowing into the second call, which then fails validation, which then reads like a coverage problem when it is a typo. The second call returns the person record. Its fields are documented on [the Person Profile migration page](/api/proxycurl-person-profile-endpoint), which is the same endpoint with the same mapping work.

The chain, end to end

```python import os, requests BASE = "https://api.richapi.ai/api/v1" H = {"x-api-key": os.environ["RICHAPI_KEY"]} def person_from_email(email: str) -> dict | None: r = requests.post(f"{BASE}/find_linkedin_url_by_email", headers=H, json={"email": email}) r.raise_for_status() # 4xx/5xx cost nothing, so fail loudly url = (r.json().get("data") or {}).get("LinkedIn Profile URL") if not url: # 2xx with no match — already billed return None p = requests.post(f"{BASE}/enrich_profile", headers=H, json={"url": url}) p.raise_for_status() return p.json() ``` The early return matters for your bill as well as your logic. When the first call resolves nothing, stop. You have already paid for that call and there is no reason to pay for a second one against an empty URL.

What the chain costs

`4 credits` for `/find_linkedin_url_by_email`, plus `1 credit` for `/enrich_profile`. A resolved email that ends in a full person record costs the sum of the two, `5 credits`. Rates are tiered by package size on [the pricing page](/pricing). **Neither endpoint is a waterfall, and both bill on any 2xx, including one that found nothing.** An email that resolves to no profile still costs you the first call. Across a list of consumer addresses and long-dead work emails that adds up fast, and it is the number to model before you run 100,000 rows. Our zero-cost-miss endpoints are the waterfalls, [email finder](/api/email-finder), [email verifier](/api/email-verifier) and [phone finder](/api/phone-finder), and none of them is in this chain. 4xx and 5xx bill nothing anywhere. Two ways to spend less on the same job. Skip call one for every record where you already store a LinkedIn URL beside the email, which in most CRMs is a meaningful share of the table. And cache the resolution: an email-to-profile mapping ages slowly compared with a job title, so re-resolving the same address every run is money spent re-learning something you knew.

The receipt on the person lookup endpoint

Both calls return an `execution_log` showing which providers ran and what each returned. On an email that resolves to nothing, that log tells you whether a source was asked and had no record, which is a more useful answer than a silent empty payload.

Use cases for this chain

**Turning inbound signups into real accounts.** A trial signup gives you a work email and nothing else. The chain fills in title, company and seniority before routing, which decides whether a human sees the account today or next quarter. **Reattaching identity to an old list.** A five-year-old export has emails and job titles that are now fiction. Resolve to a profile, re-enrich, and you learn who changed employer rather than emailing a bounced address about a role they left. **Support and fraud triage.** An unfamiliar address writes in claiming to be a buyer at a named company. One chain run tells you whether that person exists there, before anyone commits time or approves anything.

The person lookup endpoint FAQ

**Why isn't this one call?** Because resolution and enrichment are two different lookups and we bill them separately rather than hiding one inside the other. The upside is that you can skip the resolution whenever you already hold the URL. **Does a personal Gmail address work?** Try it on your own data before you assume either way. Work addresses resolve more often, and we publish no hit-rate number because a number from our sample tells you nothing about your list. **Do I pay when the email resolves to nothing?** Yes, for the first call. That is the honest answer and it is the thing to model before a bulk run. Stop the chain there and you do not pay for the second. **Can I batch this?** There are bulk endpoints in the catalog for profile and company enrichment. **What is that response key again?** `data["LinkedIn Profile URL"]`, with spaces. Write the alias once in your client model and never think about it again. **Do I need a credit card?** No. 25 free credits on signup, which is enough to run the chain several times and see what your own addresses do.

Related

- [Proxycurl alternative: the full endpoint map](/alternatives/proxycurl) — every endpoint, in one table - [Person Profile Endpoint replacement](/api/proxycurl-person-profile-endpoint) — call two of this chain, in full - [Company Profile Endpoint replacement](/api/proxycurl-company-profile-endpoint) — the company side, and the domain gap - [Employee Listing replacement](/api/proxycurl-employee-listing) — going the other way, company to people - [Email verification API](/api/email-verifier) — check the address before you send to it - [All endpoints](/api) — the full catalog - [Pricing](/pricing) — credit packages and tier rates

Try the person lookup endpoint: 25 free credits, no card

Run the chain against thirty addresses from your own list and count what resolves. **[Get 25 free credits](https://app.richapi.ai)**

Frequently asked.

What does proxycurl person lookup (email) replacement return?
Proxycurl resolved an email address to a person in one request. RichAPI does it in two: POST /find_linkedin_url_by_email returns the profile URL, then POST /enrich_profile turns that into the record. Two calls, two charges, and both of them bill on a 2xx even when the answer is empty. Price the chain, not the call.
How is this billed?
Every endpoint is billed from the same credit pool, at the published rate on /pricing — never a separate contract per endpoint.
Does this work over MCP as well as REST?
Yes — the same endpoint is reachable from an MCP client (Claude, ChatGPT, Cursor, Windsurf) using the same key and credit pool. See /mcp.

More Proxycurl Migration endpoints

See it in a workflow

Try it with 25 free credits.