LinkedIn Job Scraper API
Our LinkedIn job scraper turns a single job posting, by numeric job ID or a /jobs/view/ URL, into structured JSON: title, company, location, applicant count, salary when shown, seniority, employment type, job function, industries, and the full description in both text and HTML.
Why LinkedIn Job data is login-walled
LinkedIn's guest job page leaves the JSON-LD JobPosting block empty and server-renders the real content into classed card markup instead, so scraping the structured data returns nothing useful. Salary shows only when LinkedIn chooses to display it, and a stale job ID returns a clean 404 shell, which a naive parser reports as a crash rather than a missing posting.
Call the LinkedIn Job Scraper API in one request
curl "https://api.linkedinscraperapi.com/api/v1/linkedin/job?job_id=4406118990&api_key=$API_KEY" import requests
BASE = "https://api.linkedinscraperapi.com"
API_KEY = "YOUR_API_KEY"
# Pass a numeric job_id, or a full /jobs/view/{id} URL instead.
data = requests.get(
f"{BASE}/api/v1/linkedin/job",
params={"job_id": "4406118990", "api_key": API_KEY},
timeout=30,
).json()
print(data["title"], "@", data["company"], "-", data["location"])
print(data["seniority"], "|", data["employment_type"], "|", data["salary"])
print(data["applicants"], "-", data["posted_label"])
print(data["description"][:280]) Parameters
| Parameter | Required | Default | Notes |
|---|---|---|---|
job_id | optional | - | The numeric job ID from urn:li:jobPosting:{id}, e.g. 4406118990. One of job_id or url is required. |
url | optional | - | A full /jobs/view/{id} URL instead of the ID. One of job_id or url is required. |
api_key | required | - | Your API key, passed as a query parameter. Get one free at signup. |
The JSON the LinkedIn Job Scraper API returns
{
"id": "4406118990",
"job_id": "4406118990",
"title": "Software Engineer, New Grad",
"url": "https://www.linkedin.com/jobs/view/4406118990",
"company": "Notion",
"company_url": "https://www.linkedin.com/company/notionhq",
"location": "San Francisco, CA",
"applicants": "Over 200 applicants",
"posted_label": "3 days ago",
"salary": "$102,000.00 - $138,000.00",
"seniority": "Entry level",
"employment_type": "Full-time",
"job_function": "Engineering and Information Technology",
"industries": "Software Development",
"description": "Who We Are Notion is the collaborative AI workspace where teams and agents think together. We're building one place where your knowledge, projects, meetings, and AI tools live side by side...",
"description_html": "<p>Who We Are<br><br>Notion is the collaborative AI workspace where teams and agents think together...</p>",
"company_logo": "https://media.licdn.com/dms/image/v2/D4E0BAQGwvcv_1tHZ4w/company-logo_100_100/B4EZW25gE2GgAQ-/0/1742530282185/notionhq_logo?e=2147483647&v=beta&t=h_sgZm5R2TgP9Fpbo95m2wmxnSDoEz06eupofZwpSXs"
} | Field | Type | Description |
|---|---|---|
job_id | string | The numeric job ID, the stable identifier for the posting. |
title | string | The job title from the top card, e.g. "Software Engineer, New Grad". |
url | string | The canonical /jobs/view/{id} URL. |
company | string | The hiring company name. |
company_url | string | The hiring company's /company/ page URL. |
location | string | The job location, e.g. "San Francisco, CA". |
applicants | string | The applicant-count label when shown, e.g. "Over 200 applicants", otherwise null. |
posted_label | string | Relative posting time, e.g. "3 days ago". |
salary | string | The salary range, present only when LinkedIn displays it, e.g. "$102,000.00 - $138,000.00", otherwise null. |
seniority | string | Seniority level from the job criteria, e.g. "Entry level". |
employment_type | string | Employment type from the job criteria, e.g. "Full-time". |
job_function | string | Job function from the job criteria, e.g. "Engineering and Information Technology". |
industries | string | Industries from the job criteria, e.g. "Software Development". |
description | string | The full job description as plain text. |
description_html | string | The same description with its original HTML markup preserved. |
company_logo | string | URL of the hiring company's logo. |
Who pulls LinkedIn data, and for what
Job board aggregation
Hiring and market intelligence
Compensation benchmarking
Applicant-demand signals
Recruiting research
Talent-market dashboards
Why teams build on our LinkedIn Job Scraper API
Pass a job ID or a /jobs/view/ URL and we parse the rendered top card, the criteria list, and the description into one clean object, since the guest page leaves the JSON-LD empty. Every request runs through residential proxies with anti-bot handling and retries, returning validated JSON in about 2.6 seconds, and a removed posting comes back as a clean item-not-found rather than a parse error.
Job ID or URL input
Criteria parsed to fields
Text and HTML description
Salary when shown
Clean 404 handling
Residential-first routing
LinkedIn Job Scraper API measured against the alternatives
| Our API | DIY (requests / headless) | Official LinkedIn API | |
|---|---|---|---|
| Input by ID or URL | Yes, job_id or /jobs/view/ URL | Manual fetch and parse | No public job-by-ID endpoint |
| Structured job fields | Title, company, criteria, salary | JSON-LD is empty, parse the card | Jobs API is partner-gated |
| Setup | API key only | Residential proxies, headless browser, parsers | Talent Solutions partnership |
| Salary and applicants | Returned when LinkedIn shows them | Extra selectors, often missed | Not exposed to general apps |
| Anti-bot and proxies | Residential-first, built in | You build and maintain it | Not applicable |
| Removed postings | Clean item-not-found result | Parser crash on a 404 shell | 404 from the API |
| Full description | Text and HTML in one call | You strip and clean the markup | Only for authorized partners |
Usage-based pricing, no seats
| Plan | Price | Best for |
|---|---|---|
| Free | 1,000 requests | Testing and small jobs |
| Pro | $0.60 / 1k | Production workloads |
| Pay-as-you-go | $0.90 / 1k | Spiky or one-off volume |
Median response 2.6s. You only pay for successful requests.
FAQ
A LinkedIn job scraper is a tool that reads a public job posting and returns it in a structured format. Our LinkedIn job scraper API takes a numeric job ID or a /jobs/view/ URL and returns the title, company, location, applicant count, salary when shown, seniority, employment type, job function, industries, and the full description as JSON from a single request.
Send one GET request to our linkedin/job endpoint with a job_id or a url and your API key. We route through residential proxies, handle anti-bot checks, and parse the rendered job card and criteria list, so you get clean JSON back without maintaining selectors against LinkedIn's guest job markup.
Yes. Pass the numeric ID in job_id, for example 4406118990, or a full /jobs/view/{id} URL in url. One of the two is required, and the endpoint resolves the canonical posting URL either way.
LinkedIn only renders the salary range on postings where the employer chose to publish it, so most cards omit it. When it is present we return it as a string like "$102,000.00 - $138,000.00", and when it is not we return null. We never estimate or fabricate a pay range.
A stale or removed job ID returns a clean LinkedIn 404 shell with no top card. Our endpoint surfaces that as an item-not-found result rather than a hard parse error, so your pipeline can skip the posting and keep processing the rest of the batch.
Yes. The description comes back as plain text in the description field and with its original markup preserved in description_html, so you can index the clean text and render the formatted version. The criteria (seniority, employment type, job function, industries) come back as their own named fields alongside it.
This endpoint fetches a single posting by ID or URL. To find postings by keyword and location, use our LinkedIn search endpoint, which reads LinkedIn's public guest jobs surface and returns a list of job cards you can then expand with this job endpoint.