---
title: "LinkedIn jobs scraper"
description: "Scrape LinkedIn job search results as JSON: job title, company, location, posted date, job ID and URL. One API request from Python, Node.js, the CLI or MCP."
canonical: https://www.zenrows.com/scrape/linkedin-jobs
updated: 2026-10-20
---

# LinkedIn jobs scraper

The Zenrows LinkedIn jobs scraper turns a public LinkedIn job search URL into JSON: job ID, title, company name, company URL, location, posted date, early applicant flag, job URL and the total result count. Fetch in Adaptive Stealth Mode opens the search as a logged-out visitor, and Extract returns every job card. Run it from an API call, the CLI or an AI agent.

- Site: linkedin.com
- Returns: Job titles, companies, locations and posted dates

## Run it: one LinkedIn job search in, JSON out

```json Input
{
  "url": "https://www.linkedin.com/jobs/search?keywords=data%20engineer&location=London",
  "mode": "auto",
  "extract": "auto"
}
```

```json Output
{
  "search_context": {
    "keywords": "Data Engineer",
    "location": "London",
    "total_results": "5,000+"
  },
  "job_listings": [
    {
      "job_id": "4467786531",
      "title": "Senior Data Engineer (UK)",
      "company_name": "Firstup",
      "company_url": "https://www.linkedin.com/company/firstup-io?trk=public_jobs_jserp-result_job-search-card-subtitle",
      "location": "London, England, United Kingdom",
      "posted_date": "2026-10-07",
      "applicant_signal": "early_applicant",
      "job_url": "https://uk.linkedin.com/jobs/view/senior-data-engineer-uk-at-firstup-4467786531?position=1&pageNum=0…"
    },
    {
      "job_id": "4477149614",
      "title": "Data Engineer",
      "company_name": "Burns Sheehan",
      "company_url": "https://uk.linkedin.com/company/burnssheehan?trk=public_jobs_jserp-result_job-search-card-subtitle",
      "location": "Hemel Hempstead, England, United Kingdom",
      "posted_date": "2026-10-08",
      "applicant_signal": null,
      "job_url": "https://uk.linkedin.com/jobs/view/data-engineer-at-burns-sheehan-4477149614?position=2&pageNum=0…"
    }
  ]
}
```

Request and output of a live call to a LinkedIn job search for data engineers in London on Oct 20, 2026, trimmed to two of the 60 job cards it returned.

## What data can you scrape from LinkedIn jobs?

A LinkedIn job search returns one record per job card plus the context of the search itself. Every card in the live sample carried the fields below; the early applicant flag appears only on the jobs where LinkedIn shows it.

| Field | What it holds | Example |
|---|---|---|
| `job_listings[].job_id` | LinkedIn's numeric ID for the posting, stable across searches | `4467786531` |
| `job_listings[].title` | Job title as the employer wrote it | `Senior Data Engineer (UK)` |
| `job_listings[].posted_label` | The title text shown on the card | `Senior Data Engineer (UK)` |
| `job_listings[].company_name` | The hiring company | `Firstup` |
| `job_listings[].company_url` | The company's LinkedIn page | `https://www.linkedin.com/company/firstup-io?trk=…` |
| `job_listings[].company_logo_url` | Company logo image | `https://media.licdn.com/dms/image/v2/…` |
| `job_listings[].location` | City, region and country of the role | `London, England, United Kingdom` |
| `job_listings[].posted_date` | Date the job was listed, as YYYY-MM-DD | `2026-10-07` |
| `job_listings[].applicant_signal` | Set when LinkedIn marks the job for early applicants | `early_applicant` |
| `job_listings[].job_url` | Link to the job page | `https://uk.linkedin.com/jobs/view/…-4467786531?…` |
| `search_context.keywords` | The keywords LinkedIn read from the URL | `Data Engineer` |
| `search_context.location` | The location LinkedIn read from the URL | `London` |
| `search_context.total_results` | LinkedIn's count of matching jobs | `5,000+` |

For company records (industry, size, headquarters, followers) behind each `company_url`, use the [LinkedIn scraper](/scrape/linkedin).

## How to scrape LinkedIn jobs with Zenrows

1. **Create a free Zenrows account** and copy your API key from the dashboard.
2. **Build the search in a browser.** Open `linkedin.com/jobs/search` while logged out, type the keywords and location, set any filters (date posted, remote, experience level), and copy the URL from the address bar. The query string carries every choice.
3. **Send the URL with the default configuration**: Adaptive Stealth Mode to open the search and Extract to return the job cards. The location comes from the URL, so you don't need to set a country.
4. **Read `parsed.job_listings`** and store each card under its `job_id`. Ask for only the fields you need with their paths.
5. **Run all your searches in Batch** on a schedule, and keep the job IDs you have not seen before.

```python Python
# pip install requests
import requests

params = {
    "apikey": "YOUR_ZENROWS_API_KEY",
    "url": "https://www.linkedin.com/jobs/search?keywords=data%20engineer&location=London",
    "mode": "auto",      # Adaptive Stealth Mode
    "extract": "auto",   # structured JSON
}
response = requests.get("https://api.zenrows.com/v1/", params=params, timeout=180)
response.raise_for_status()

parsed = response.json()["parsed"]
print(parsed["search_context"]["total_results"], "jobs for", parsed["search_context"]["keywords"])
for job in parsed["job_listings"]:
    print(job["job_id"], job["posted_date"], job["title"], "|", job["company_name"], "|", job["location"])
```

```javascript Node.js
// Node 18+ (built-in fetch)
const params = new URLSearchParams({
  apikey: "YOUR_ZENROWS_API_KEY",
  url: "https://www.linkedin.com/jobs/search?keywords=data%20engineer&location=London",
  mode: "auto",
  extract: "auto",
});

const response = await fetch(`https://api.zenrows.com/v1/?${params}`, {
  signal: AbortSignal.timeout(180_000),
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);

const { parsed } = await response.json();
const rows = parsed.job_listings.map((j) => [j.job_id, j.title, j.company_name, j.posted_date]);
console.table(rows);
```

```bash cURL
curl "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.linkedin.com%2Fjobs%2Fsearch%3Fkeywords%3Ddata%2520engineer%26location%3DLondon&mode=auto&extract=auto"

# Only the fields you need
curl "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.linkedin.com%2Fjobs%2Fsearch%3Fkeywords%3Ddata%2520engineer%26location%3DLondon&mode=auto&extract=auto&extract_fields=job_listings.job_id%2Cjob_listings.title%2Cjob_listings.company_name%2Cjob_listings.posted_date"
```

```python Python SDK
# pip install zenrows
from zenrows import ZenRowsClient

client = ZenRowsClient("YOUR_ZENROWS_API_KEY")
response = client.get(
    "https://www.linkedin.com/jobs/search?keywords=python&location=United%20States",
    params={"mode": "auto", "extract": "auto"},
)
jobs = response.json()["parsed"]["job_listings"]
hiring = sorted({job["company_name"] for job in jobs})
print(len(jobs), "jobs from", len(hiring), "companies:", ", ".join(hiring))
```

## Input

The scraper takes one LinkedIn job search URL per request. Keywords, location and filters all travel inside the URL, so a list of searches is a list of URLs with the same settings below.

| Parameter | Type | Default | Description |
|---|---|---|---|
| `url` | string | required | A LinkedIn job search, `https://www.linkedin.com/jobs/search?keywords=…&location=…`, with any filters you set in the browser |
| `mode` | string | `auto` | Adaptive Stealth Mode: starts with the lightest setup and adds rendering and protected-site handling only when the page needs them |
| `extract` | string | `auto` | Returns the job cards as JSON in `parsed`, next to the raw `html` |
| `extract_fields` | string | all fields | Comma-separated paths to keep, such as `job_listings.job_id,job_listings.title,job_listings.posted_date` |
| `proxy_country` | string | any | Two-letter country code, optional. The search location is already in the URL |
| `wait_for` | string | none | A CSS selector to wait for before the page is read |

```json Batch input
{
  "type": "regular",
  "status": "closed",
  "zenrows_params": {
    "mode": "auto",
    "extract": "auto"
  },
  "tasks": [
    { "url": "https://www.linkedin.com/jobs/search?keywords=data%20engineer&location=London", "external_id": "data-engineer-london" },
    { "url": "https://www.linkedin.com/jobs/search?keywords=python&location=United%20States", "external_id": "python-us" }
  ]
}
```

## Output

Every response is JSON with two keys: `html`, the search page as LinkedIn served it, and `parsed`, the structured record. Both samples below are trimmed outputs of live requests to two different searches.

```json Data engineer jobs in London
{
  "search_context": {
    "keywords": "Data Engineer",
    "location": "London",
    "total_results": "5,000+"
  },
  "job_listings": [
    {
      "applicant_signal": null,
      "company_logo_url": "https://media.licdn.com/dms/image/v2/C4D0BAQE3Zb1kkMYY6g/company-logo_100_100/…/oviva_logo",
      "company_name": "Oviva",
      "company_url": "https://ch.linkedin.com/company/oviva?trk=public_jobs_jserp-result_job-search-card-subtitle",
      "job_id": "4468656126",
      "job_url": "https://uk.linkedin.com/jobs/view/staff-data-engineer-at-oviva-4468656126?position=3&pageNum=0…",
      "location": "London, England, United Kingdom",
      "posted_date": "2026-10-08",
      "posted_label": "Staff Data Engineer",
      "title": "Staff Data Engineer"
    },
    {
      "applicant_signal": null,
      "company_logo_url": "https://media.licdn.com/dms/image/v2/D4E0BAQHfuDEWpxxPgQ/company-logo_100_100/…/miq_digital_logo",
      "company_name": "MiQ",
      "company_url": "https://uk.linkedin.com/company/miq-digital?trk=public_jobs_jserp-result_job-search-card-subtitle",
      "job_id": "4468720351",
      "job_url": "https://uk.linkedin.com/jobs/view/junior-data-engineer-at-miq-4468720351?position=4&pageNum=0…",
      "location": "London, England, United Kingdom",
      "posted_date": "2026-10-13",
      "posted_label": "Junior Data Engineer",
      "title": "Junior Data Engineer"
    }
  ]
}
```

```json Python jobs in the United States
{
  "search_context": {
    "keywords": "Python",
    "location": "United States",
    "total_results": "11,000+"
  },
  "job_listings": [
    {
      "applicant_signal": null,
      "company_name": "Venmo",
      "company_url": "https://www.linkedin.com/company/venmo?trk=public_jobs_jserp-result_job-search-card-subtitle",
      "job_id": "4465379983",
      "job_url": "https://www.linkedin.com/jobs/view/senior-software-engineer-python-at-venmo-4465379983?position=1&pageNum=0…",
      "location": "Austin, TX",
      "posted_date": "2026-10-01",
      "title": "Senior Software Engineer - Python"
    },
    {
      "applicant_signal": "early_applicant",
      "company_name": "Northrop Grumman",
      "company_url": "https://www.linkedin.com/company/northrop-grumman-corporation?trk=public_jobs_jserp-result_job-search-card-subtitle",
      "job_id": "4475356230",
      "job_url": "https://www.linkedin.com/jobs/view/python-software-engineer-level-2-or-3-aht-at-northrop-grumman-4475356230?position=2&pageNum=0…",
      "location": "Aurora, CO",
      "posted_date": "2026-10-03",
      "title": "Python Software Engineer Level 2 or 3 (AHT)"
    }
  ]
}
```

US searches return city and state (`Austin, TX`), while UK searches return city, region and country. Normalize `location` before you group jobs by place.

## Scrape LinkedIn jobs from your coding agent

Claude Code, Cursor, Codex and any MCP client can run a LinkedIn job search from a prompt and hand back a table.

The agent sends the same Fetch and Extract request shown above and reads the same job cards. Connect the Zenrows MCP server once, or install the CLI and let the agent call it in the terminal.

```bash Connect the MCP server (Claude Code)
claude mcp add zenrows -e ZENROWS_API_KEY=YOUR_ZENROWS_API_KEY -- npx -y @zenrows/mcp
```

```json MCP config (Cursor, Claude Desktop, Windsurf)
{
  "mcpServers": {
    "zenrows": {
      "command": "npx",
      "args": ["-y", "@zenrows/mcp"],
      "env": { "ZENROWS_API_KEY": "YOUR_ZENROWS_API_KEY" }
    }
  }
}
```

```bash Or run the CLI
npx -y @zenrows/cli init
zenrows extract "https://www.linkedin.com/jobs/search?keywords=data%20engineer&location=London"
```

```text Then ask your agent
Use Zenrows to read this LinkedIn job search and list the companies
hiring, with how many open roles each has and the newest posted date:
https://www.linkedin.com/jobs/search?keywords=data%20engineer&location=London
```

## Scrape LinkedIn jobs at scale with Batch and Crawl

**Batch** runs many job searches as one job, in parallel, with your own ID on each result. A typical setup is one search per keyword and city pair, run every morning, with the new `job_id` values written to a database.

**Crawl** starts from a search page and follows the links to each job posting. Keep the links that contain `/jobs/view/` and ask for Markdown, and it returns the full text of every posting it reaches: description, seniority level and employment type included.

```bash Batch (cURL)
curl -X POST "https://async.api.zenrows.com/v1/jobs" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "regular",
    "status": "closed",
    "zenrows_params": { "mode": "auto", "extract": "auto" },
    "tasks": [
      { "url": "https://www.linkedin.com/jobs/search?keywords=data%20engineer&location=London", "external_id": "data-engineer-london" },
      { "url": "https://www.linkedin.com/jobs/search?keywords=python&location=United%20States", "external_id": "python-us" }
    ]
  }'

# Read the results when the job finishes
curl "https://async.api.zenrows.com/v1/jobs/JOB_ID/results?status=successful" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY"
```

```bash Batch (CLI)
# searches.jsonl: one {"url": "...", "external_id": "...", "extract": "auto"} per line
zenrows batch create searches.jsonl --wait
zenrows batch results <job-id> --out linkedin-jobs.jsonl
```

```bash Crawl (cURL)
curl -X POST "https://api.zenrows.com/v1/crawls" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.linkedin.com/jobs/search?keywords=data%20engineer&location=London",
    "depth": 1,
    "max_pages": 100,
    "include_patterns": ["/jobs/view/"],
    "output_format": "markdown"
  }'
```

**Scheduled jobs** run the same Batch job on a timetable, on Zenrows' side: every few hours, once a day, at set times on chosen days, or once at a future date. Each run keeps its own results, a webhook can tell your app when a run finishes, and you can pause or resume the schedule at any time, with no cron server to keep alive.

```bash Scheduled job (cURL)
# Runs every day on Zenrows' side; each run keeps its own results
curl -X POST "https://async.api.zenrows.com/v1/jobs" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
      "type": "scheduled",
      "status": "closed",
      "schedule": {
        "rate": {
          "every": 1,
          "unit": "day"
        }
      },
      "zenrows_params": {
        "mode": "auto",
        "extract": "auto"
      },
      "tasks": [
        {
          "url": "https://www.linkedin.com/jobs/search?keywords=data%20engineer&location=London",
          "external_id": "linkedin-jobs"
        }
      ]
    }'

# Or at set times: "schedule": { "calendar": { "times_of_day": ["09:00"],
#   "cadence": { "weekly": { "days": ["mon", "thu"] } } }, "timezone": "Europe/Madrid" }
```

## What teams do with LinkedIn job data

| Use case | Data they pull | Who runs it |
|---|---|---|
| Hiring signals for sales | Companies with open roles for a keyword, how many and since when | SDR teams and sales ops |
| Job aggregators and boards | Title, company, location, posted date and job URL across many searches | Job board and HR tech companies |
| Labor market research | Result counts and titles by skill and city, tracked weekly | Economists, analysts and universities |
| Recruiting pipeline sourcing | Companies hiring for roles a staffing firm fills | Recruitment agencies |
| Competitor hiring watch | New postings by a rival's company name, by function and location | Strategy and talent teams |
| Investment research | Hiring pace at portfolio or target companies as a growth proxy | Investors and alternative data teams |

## Tips for scraping LinkedIn jobs

- **Dedupe on `job_id`.** The same posting shows up in several searches and on several days. The ID is stable; the `job_url` is not, because it carries position and tracking parameters.
- **Rebuild a clean job URL from the ID.** `https://www.linkedin.com/jobs/view/<job_id>` opens the same posting without the tracking query string.
- **Use LinkedIn's filters in the URL.** `f_TPR=r86400` keeps jobs from the past 24 hours, `f_WT=2` keeps remote roles and `f_E` sets the experience level. Set them in the browser, then copy the URL.
- **Split broad searches.** The London search above reports "5,000+" matches and returned 60 cards. For full coverage, run narrower searches (one per city, per keyword, per day) instead of one broad one.
- **Run daily with a short date window.** A past-24-hours filter on a daily schedule catches new jobs with fewer pages than re-reading a whole search.
- **Join to company pages.** Each card's `company_url` points to the company's LinkedIn page. Send those through the [LinkedIn scraper](/scrape/linkedin) to add industry and headcount to every job.

## Frequently asked questions

### Is it legal to scrape LinkedIn jobs?

Job listings are published for anyone to see, and collecting public listings is common practice for job boards and labor market research. Listings carry company data rather than personal data, but if you also collect recruiter or member details, the GDPR and the CCPA apply. LinkedIn's User Agreement restricts automated collection, so check its terms for your use case and ask your lawyer if you are unsure.

### Is there an official LinkedIn jobs API?

LinkedIn's Job Posting API exists for approved applicant tracking systems and job distribution partners, and it is for publishing jobs to LinkedIn, not for reading other companies' listings. There is no public API that returns LinkedIn job search results, which is why teams use a scraper.

### What LinkedIn job pages can I scrape?

Job search pages on linkedin.com and its country subdomains, with any keywords, location and filters in the URL. Single job pages ( /jobs/view/<id> ) work too: request them as Markdown, or read the html , to get the full posting text.

### Can I get the full job description?

Yes. The search returns the card fields, and the job page holds the description, seniority level, employment type and industry. Request each job page as Markdown, or use Crawl with Markdown output to collect every posting from a search in one run.

### Do I need a LinkedIn account to scrape jobs?

No. LinkedIn's job search is public, and Zenrows opens it as a logged-out visitor. You never share an account or cookie, so none of your LinkedIn accounts is at risk.

### How do I scrape LinkedIn jobs with Python?

Send a GET request to https://api.zenrows.com/v1/ with your API key, the job search URL, Adaptive Stealth Mode and Extract turned on, as in the Python example above. Loop over parsed["job_listings"] to read each card. The zenrows package on PyPI wraps the same request.

### Can AI agents scrape LinkedIn jobs with Zenrows?

Yes. Connect the Zenrows MCP server to Claude, Cursor, Codex or any MCP client, or give your agent the Zenrows CLI. Paste a search URL or describe the search, and the agent calls Fetch and Extract for you.

### Can I scrape LinkedIn on a schedule?

Yes. Create a scheduled Batch job with your LinkedIn URLs and the same settings as a single request, and Zenrows runs it on its side: every few hours, once a day, at set times on chosen days, or once at a future date. Each run keeps its own results, a webhook can notify your app when a run finishes, and the schedule can be paused or resumed at any time.

### Which integrations work with the LinkedIn jobs scraper?

Zenrows works with n8n, Make, Zapier, Clay, Dify, LangChain, LlamaIndex, CrewAI and Mastra, plus the Python, Node.js and Go SDKs and any HTTP client. A common workflow is a daily n8n or Make run that sends new jobs to Google Sheets, Slack or a CRM. See the integrations page for the full list.

### What format does the data come in?

JSON by default, with the job cards in parsed and the original page in html . You can also ask for Markdown or plain text, which suits job descriptions you plan to feed to an LLM.

## More LinkedIn scrapers

- [LinkedIn scraper](https://www.zenrows.com/scrape/linkedin.md)
- [LinkedIn profile scraper](https://www.zenrows.com/scrape/linkedin-profile.md)
- [LinkedIn post scraper](https://www.zenrows.com/scrape/linkedin-posts.md)

All scrapers: https://www.zenrows.com/scrape. Start free: https://app.zenrows.com/register. Docs: https://docs.zenrows.com
