Data catalog · Proxycurl Migration

Proxycurl Person Profile Endpoint replacement

Proxycurl's Person Profile Endpoint took a LinkedIn profile URL and returned a person record. POST /enrich_profile takes the same input and returns the same kind of record under different field names. The URL swap is ten minutes; re-mapping the fields is the afternoon. This page covers both, and is clear that a 2xx bills even when the record comes back thin.

Try this live — 25 free credits

Last updated September 22, 2026

Your Person Profile calls are returning errors. Here is the one that works.

Proxycurl is gone, so every `GET` against its Person Profile Endpoint now fails and your enrichment jobs are writing nulls. The replacement is `POST /enrich_profile`. It takes the same thing yours already has, a LinkedIn profile URL, so nothing upstream in your pipeline has to change. **[Get 25 free credits — no card](https://app.richapi.ai)** Of the four Proxycurl endpoints people are migrating off, this is the cleanest. Same input type, same kind of output, different field names. Budget the afternoon for the field names, not for the call.

The before and after

```bash # Before (Proxycurl) — dead # GET https://nubela.co/proxycurl/api/v2/linkedin?url=<profile-url> # -H "Authorization: Bearer $PROXYCURL_KEY" # Proxycurl's public docs are offline. Confirm paths against your own archived client code before you migrate. # After (RichAPI) 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/"}' ``` Three mechanical changes: `GET` with a query string becomes `POST` with a JSON body, `Authorization: Bearer` becomes `x-api-key`, and the parameter is `url`. There is no OAuth step and no token exchange.

The field mapping is the actual work

Both APIs return a person, but they disagree on what to call the parts of one. RichAPI's response is flat JSON with these fields: | Field | Type | What it holds | |---|---|---| | `firstname` | string | Given name | | `lastname` | string | Family name | | `headline` | string | The line under the name on the profile | | `summary` | string | The About section | | `location` | string | Location as the profile states it | | `currentCompany` | string | Employer on the current role | | `currentTitle` | string | Title on the current role | | `profilePicture` | string | Image URL | | `connectionCount` | number | Connections | | `followerCount` | number | Followers | | `linkedinUrl` | string | Canonical profile URL | | `experience` | array | Role history | | `education` | array | Schools | | `skills` | array | Listed skills | | `certifications` | array | Listed certifications | | `languages` | array | Listed languages | Two differences will bite you if you skip them. RichAPI splits the name into `firstname` and `lastname` where Proxycurl carried a single full-name field, so any code doing `record.full_name.split()` needs deleting rather than porting. And the arrays are the part your adapter should treat as untrusted: if you were reading a nested key off a Proxycurl experience entry, check the live shape before you write the mapping. The authority is `https://api.richapi.ai/api/v1/openapi.json`. Read fields off that, not off this table, because this table is a page and that is the spec.

Migrate in four steps

**1. Get a key.** Sign up at [app.richapi.ai](https://app.richapi.ai), 25 free credits, no card. **2. Change the call.** Swap host, method and auth header as shown above. If your Proxycurl client was a thin wrapper, this is a single function. **3. Write the mapping in one place.** Put a `from_richapi(payload)` function between the API and the rest of your code, returning whatever internal person object you already use. Everything downstream then keeps compiling untouched, and when the response gains a field you edit one function. **4. Replay records you already know.** Take twenty profiles where you still have the old Proxycurl output in your database, run them through the new call, and diff. That comparison tells you your real coverage on your real accounts, which no vendor page can. Calling it from an agent works too. The [hosted MCP server](/integrations/claude) exposes `enrich_profile` as a tool in Claude, Cursor and VS Code, which is a fast way to eyeball the response shape before you write the adapter.

What a call costs, and when you pay

`1 credit` per call, flat. Credits are prepaid with no seats, no subscription and no contract; the per-credit rate is tiered by package size, so read yours from [the pricing page](/pricing). **This endpoint is not a multi-provider waterfall, and every 2xx is billed, including one that comes back thin.** We do have endpoints where a miss costs zero credits, [email finder](/api/email-finder) and [email verifier](/api/email-verifier) among them, and this is not one of them. If you are re-enriching a stale list of 50,000 profile URLs, budget for 50,000 charges and not for the subset that resolves. 4xx and 5xx responses cost nothing on any endpoint.

The receipt on the person profile endpoint

A thin record here raises one question. Was there nothing to find, or did the routing go wrong? `execution_log` answers it, listing the providers tried, the order, and what each one returned, which is the difference between a data problem and a routing problem. Proxycurl gave you a status code and left you guessing.

What people use the person profile endpoint for

**Restarting a stalled CRM sync.** The nightly job that hydrated contact records off LinkedIn URLs has been failing since the shutdown. Point it here, map the fields once, and the backlog drains on the next run. **Candidate screening inside an ATS.** `experience` and `education` are what the screen reads, and the recruiter is looking at the record while the call happens rather than overnight. **An agent that researches a person mid-conversation.** Through MCP the profile lookup is a tool call, so the agent pulls a record when it decides it needs one instead of you pre-enriching a list you hope it will use.

The person profile endpoint FAQ

**Is this a drop-in replacement?** The request is close to one. The response is not, because the field names differ. Plan for a mapping layer, and do not deploy a find-and-replace on a Friday. **Can I pass a vanity URL, or a URL with tracking parameters on it?** Send the clean `linkedin.com/in/<slug>/` form. **Do I get charged when the profile comes back nearly empty?** Yes. A 2xx is billed on this endpoint whatever it contains. Zero-cost misses apply to the waterfall endpoints, not to this one. **What about the profiles I used to resolve from an email address?** That is a two-call chain now. See [the Person Lookup migration](/api/proxycurl-person-lookup-email). **How fresh is the record?** It is retrieved at request time rather than read out of a snapshot we refresh on a schedule. We do not sell an index size, because people change jobs and an index does not. **Can I call this from Claude or Cursor?** Yes, through the hosted MCP server, no install. The tool list updates itself as endpoints change. **Do I need a credit card to test the migration?** No. 25 free credits on signup.

Related

- [Proxycurl alternative: the full endpoint map](/alternatives/proxycurl) — every endpoint, in one table - [Company Profile Endpoint replacement](/api/proxycurl-company-profile-endpoint) — the company-side swap, and the domain problem - [Person Lookup by email replacement](/api/proxycurl-person-lookup-email) — the two-call chain - [Employee Listing replacement](/api/proxycurl-employee-listing) — everyone at a company - [All endpoints](/api) — the full catalog - [Pricing](/pricing) — credit packages and tier rates

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

Run twenty profiles you already have answers for and diff them against your old output. **[Get 25 free credits](https://app.richapi.ai)**

Frequently asked.

What does proxycurl person profile endpoint replacement return?
Proxycurl's Person Profile Endpoint took a LinkedIn profile URL and returned a person record. POST /enrich_profile takes the same input and returns the same kind of record under different field names. The URL swap is ten minutes; re-mapping the fields is the afternoon. This page covers both, and is clear that a 2xx bills even when the record comes back thin.
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.