A LinkedIn API built on public data: one GET request returns a profile, company page, posts, or jobs as clean JSON. One credit per successful call, and an inaccessible profile costs nothing.
Everything lives at GET /v1/linkedin. Pick a surface with type, pass a URL or keywords, and the result comes back under a key named after the type.
Most tools in this space sell a LinkedIn profile API, a company API, and a jobs API as separate products with separate pricing. Here it is one LinkedIn data API with one billing rule: a successful call is one credit, an empty or inaccessible result is free.
| type | What comes back | Input |
|---|---|---|
| profile | The full public profile: name, headline, work history, education, follower count, and more. The default type. | url (a linkedin.com/in/... URL) |
| refresh | The current company and school with their numeric LinkedIn ids, plus companyState. Markedly faster than a full profile read, built for keeping a database current. | url |
| company | The public company page. Add employees=true for the employee list. | url (a linkedin.com/company/... URL) |
| posts | Public posts, up to 100 per call. Add comments=true for comments on each post. | url (profile or company) |
| jobs | Public job listings, up to 50 per call, with paging via start. | keywords plus optional location, or a job url |
| search (beta) | People search. Add enrich=true to get each person's full profile in the same call. | keywords |
Note the input rule: profile, company, and posts take url, never a search query. If you only have a name, find the person first with type=search (beta), then pass the profile URL you get back.
This is the exact JSON the curl above returned, trimmed for width. It came back in 800 ms and cost 1 credit.
Two fields worth noticing. accessible tells you whether the profile has a public page at all; when it is false, profile is null, a note explains why, and the call is not charged. memberIdentifier is LinkedIn's permanent numeric member id, which survives name and vanity-URL changes, so it is the right join key for a database.
The whole public record, structured. Same shape on every call, so your parser is written once.
The email field is opt-in: add email=true to a profile call and the response appends workEmail and emailStatus. The status is verified, pattern-likely, or unknown, so you can filter to the addresses that were actually confirmed and treat the rest as guesses. Email rides along as a field on the profile call, it is not a separate product.
Fields that only exist behind a login stay out, on purpose. A person's connection list, mutual connections, who viewed a profile, or anything else that never appears on the logged-out page is not in the response. That boundary is what lets the API run with no accounts and nothing of yours at risk. If you need logged-in fields, a tool that runs on your own session can pull them, at that account's risk.
A handful of plain-English options. Everything else has a sane default.
| Parameter | Applies to | What it does |
|---|---|---|
| url | profile, refresh, company, posts, jobs | A linkedin.com URL. Required for profile, company, and posts. jobs accepts a job URL instead of keywords. |
| keywords | search (beta), jobs | What to search for. Required for search; required for jobs unless you pass a job URL. |
| location | jobs | City or region filter for the job search. |
| limit | jobs, posts, search (beta) | How many results. jobs: default 25, max 50. posts: default 50, max 100. search: default 10, max 15. |
| start | jobs | Result offset for paging. |
| profile | Appends workEmail and emailStatus (verified, pattern-likely, or unknown) to the profile. | |
| enrich | search (beta) | Returns each person's full profile in the same call. Bills 1 credit per full profile returned instead of 1 per call. |
| employees | company | Includes the employee list on the company page. |
| comments | posts | Includes comments on each post. |
| member | refresh | Also returns memberIdentifier. Opt-in because it is a slower read; the id never changes, so fetch it once and keep it. |
| headline | profile | For profiles whose companyState is restricted, attempts to recover the member's own public headline. Best effort, roughly one in twenty. |
Keeping a database current should not take one HTTP round trip per row. Send up to 100 profile URLs in one POST and get results back in input order.
The rules are built for large runs: results come back in the same order you sent them, a failing row never fails the batch, and a malformed URL comes back as a per-row error instead of a charge. Billing matches the single endpoint, one credit per successful row and not-accessible rows free. type can be refresh (the default, current company and school with numeric ids) or profile (the full record), and member: true adds memberIdentifier on refresh rows.
One billing rule across every type, and you only pay when data actually comes back.
Every successful call is one credit, whatever the type. The one exception is spelled out above: people search (beta) with enrich=true bills one credit per full profile it returns. A private or empty profile returns a null result with a note and is not charged, and an empty search result is free.
Credits are prepaid and never expire. The free tier is 3,000 credits every month with no card. Paid packs start at 25,000 credits for $49, which works out to $1.96 per 1,000 calls, and the rate drops as packs get bigger.
Related: Scrape LinkedIn without login · LinkedIn Profile Scraper · Bright Data LinkedIn alternative · Proxycurl alternative
Start on the free 3,000 credits a month, no card needed. One GET returns the public profile as clean JSON, and a profile that is not accessible costs you nothing. No account of yours is ever part of the request.
Get 3,000 free credits