# LinkedIn Jobs Scraper (`parsebird/linkedin-jobs-scraper`) Actor

Scrape LinkedIn job postings by keyword and location without login: title, company, salary range, seniority, employment type, full description, location with coordinates, and posting dates.

- **URL**: https://apify.com/parsebird/linkedin-jobs-scraper.md
- **Developed by:** [ParseBird](https://apify.com/parsebird) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.34 / 1,000 linkedin jobs

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### LinkedIn Jobs Scraper

LinkedIn Jobs Scraper extracts **job postings from LinkedIn job search** by keyword and location, with no LinkedIn account and no cookies. Each job comes with the title, company, salary range, seniority, employment type, full description, posting and expiry dates, and a geocoded location.

<table><tr>
<td style="border-left:4px solid #0A66C2;padding:12px 16px;font-weight:600">
Search LinkedIn jobs by keyword, location, and date posted, keep only the job types and experience levels you want, and get 30+ structured fields per posting — salary range, seniority, requisition ID, coordinates, and the full description as text and bullets.
</td>
</tr></table>

<br>

<table>
<tr>
<td colspan="3" style="padding:10px 14px;background:#0A66C2;border:none;border-radius:4px 4px 0 0">
<span style="color:#FFFFFF;font-size:14px;font-weight:700;letter-spacing:0.5px">ParseBird LinkedIn Suite</span>
<span style="color:#CFE4FA;font-size:13px">&nbsp;&nbsp;&bull;&nbsp;&nbsp;Companies, jobs &amp; B2B leads</span>
</td>
</tr>
<tr>
<td style="padding:10px 14px;border:1px solid #E7E5E4;border-radius:0 0 0 4px;border-right:none;border-top:none;vertical-align:top;width:33%;background:#FFFFFF">
<a href="https://apify.com/parsebird/linkedin-company-scraper" style="color:#1C1917;text-decoration:none;font-weight:700;font-size:13px">LinkedIn Company Scraper Bulk</a><br>
<span style="color:#78716C;font-size:11px">Company profiles in bulk, no cookies</span>
</td>
<td style="padding:10px 14px;border:1px solid #E7E5E4;border-top:none;vertical-align:top;width:33%;background:#E8F1FB">
<a href="https://apify.com/parsebird/linkedin-jobs-scraper" style="color:#0A66C2;text-decoration:none;font-weight:700;font-size:13px">LinkedIn Jobs Scraper</a><br>
<span style="color:#0A66C2;font-size:11px;font-weight:600">You are here</span>
</td>
<td style="padding:10px 14px;border:1px solid #E7E5E4;border-radius:0 0 4px 0;border-top:none;vertical-align:top;width:33%;background:#FFFFFF">
<a href="https://apify.com/parsebird/linkedin-b2b-phone-number-scraper" style="color:#1C1917;text-decoration:none;font-weight:700;font-size:13px">LinkedIn B2B Phone Number Scraper</a><br>
<span style="color:#78716C;font-size:11px">B2B phone numbers &amp; emails</span>
</td>
</tr>
</table>

##### Copy to your AI assistant

Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this actor.

```
Actor: parsebird/linkedin-jobs-scraper — scrapes public LinkedIn job postings without login or cookies. Input: {"keywords": "software engineer", "location": "San Francisco, CA", "maxItems": 100, "datePosted": "any"|"past24h"|"pastWeek"|"pastMonth", "jobTypes": ["fullTime","partTime","contract","temporary","internship","volunteer","other"], "experienceLevels": ["internship","entryLevel","associate","midSenior","director","executive"]} (at least one of keywords or location; filters optional; use location "Remote" for remote jobs). Run via ApifyClient("YOUR_TOKEN").actor("parsebird/linkedin-jobs-scraper").call(run_input=input). Output: one item per job with title, company, companyUrl, companyLogo, location, postedAt, postedTimeAgo, validThrough, employmentType, seniorityLevel, jobFunction, industry, workplaceType, applicantsCount, salary, salaryCurrency, salaryMinValue, salaryMaxValue, salaryUnit, experienceMonths, educationRequirement, linkedinJobId, jobId, addressLocality, addressRegion, addressCountry, latitude, longitude, description, descriptionBullets, jobUrl, sourceUrl, scrapedAt. Pricing: pay per job. Get your API token at https://console.apify.com/account#/integrations. Full API spec: https://apify.com/parsebird/linkedin-jobs-scraper/api
```

### What is LinkedIn Jobs Scraper?

LinkedIn Jobs Scraper is a **LinkedIn job scraper** that runs a search on [LinkedIn Jobs](https://www.linkedin.com/jobs/) the way a logged-out visitor would, then opens every job posting and turns it into clean, structured data. It works as a **LinkedIn Jobs API alternative** for job boards, recruiting, salary research, and labor-market analysis.

The easiest way to try it: keep the example search (`software engineer` in `San Francisco, CA`), click **Start**, and open the dataset a few seconds later.

No LinkedIn login or cookies are used, so there is no account that can be restricted.

### What can LinkedIn Jobs Scraper do?

- 🔎 **Search by keywords, location, or both** — job titles, skills, companies, cities, regions, countries, `Remote`, or worldwide.
- 🎛️ **Filters** — date posted (past 24 hours, week, or month), job type, and experience level. Job type and experience level are checked on each posting, and only matching jobs are saved and charged.
- 📈 **Past LinkedIn's ~500 result limit** — one LinkedIn search shows about 500 jobs; larger runs repeat the search over recent time windows to reach more postings.
- 💰 **Structured salary** — the pay range text plus currency, minimum, maximum, and unit when the employer provides it.
- 📍 **Geocoded locations** — city, region, country, latitude, and longitude.
- 📝 **Full descriptions** — as plain text and as a list of paragraphs and bullet points.
- 🧾 **Deduplicated** — each LinkedIn job is saved once per run.

As an Apify Actor it also gives you [scheduling](https://docs.apify.com/platform/schedules), a [REST API](https://docs.apify.com/api/v2), [integrations](https://apify.com/integrations) with Make, Zapier, Google Sheets, Slack, and webhooks, and exports to JSON, CSV, Excel, XML, or HTML.

### What data can you extract from LinkedIn Jobs?

| Field | Description |
|-------|-------------|
| `title`, `company`, `companyUrl`, `companyLogo` | Job title and hiring company |
| `location`, `addressLocality`, `addressRegion`, `addressCountry` | Location as shown and as structured fields |
| `latitude`, `longitude` | Geo-coordinates of the job location |
| `postedAt`, `postedTimeAgo`, `validThrough` | Posting date, relative age, and application deadline |
| `employmentType`, `seniorityLevel`, `jobFunction`, `industry` | Job classification |
| `workplaceType` | `Remote` when LinkedIn marks the job as remote |
| `applicantsCount` | Applicant count as shown, e.g. "Over 200 applicants" |
| `salary`, `salaryCurrency`, `salaryMinValue`, `salaryMaxValue`, `salaryUnit` | Pay range as text and as numbers |
| `experienceMonths`, `educationRequirement` | Required experience and education, when listed |
| `linkedinJobId` | LinkedIn's job ID, unique per posting |
| `jobId` | The employer's own requisition ID; one requisition posted in several cities appears as several postings with the same `jobId` |
| `description`, `descriptionBullets` | Full description as text (one line per paragraph or list item) and as a list |
| `jobUrl`, `sourceUrl`, `scrapedAt` | Link to the posting and scrape time |

Fields the employer didn't fill in are `null`.

### How to scrape LinkedIn jobs

1. Open [LinkedIn Jobs Scraper](https://apify.com/parsebird/linkedin-jobs-scraper) and click **Try for free**.
2. Enter **Keywords** (e.g. `product manager`), a **Location** (e.g. `London`), or both.
3. Optionally set **Date posted**, **Job type**, and **Experience level**.
4. Set **Maximum jobs** and click **Start**.
5. Download the jobs from the **Output** tab as JSON, CSV, or Excel, or read them through the API.

### Input

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `keywords` | string | One of keywords/location | — | Job title or keywords |
| `location` | string | One of keywords/location | — | City, region, or country |
| `maxItems` | integer | No | 10 | How many jobs to collect (up to 10,000) |
| `datePosted` | string | No | `any` | `any`, `past24h`, `pastWeek`, `pastMonth` |
| `jobTypes` | array | No | all | Keep only `fullTime`, `partTime`, `contract`, `temporary`, `internship`, `volunteer`, `other` |
| `experienceLevels` | array | No | all | Keep only `internship`, `entryLevel`, `associate`, `midSenior`, `director`, `executive` |
| `proxyConfiguration` | object | No | off | Optional fallback proxy for requests that stay blocked |

Example input:

```json
{
  "keywords": "software engineer",
  "location": "San Francisco, CA",
  "maxItems": 100
}
```

### Output example

```json
{
  "title": "Senior Development Engineer I",
  "company": "Yokohama Tire Corporation",
  "companyUrl": "https://www.linkedin.com/company/yokohamatirecorp",
  "companyLogo": "https://media.licdn.com/dms/image/v2/C560BAQFcm0yog2D3NA/company-logo_200_200/...",
  "location": "Cornelius, NC",
  "postedAt": "2026-09-28T20:56:26.000Z",
  "postedTimeAgo": "5 days ago",
  "validThrough": "2026-10-28T20:56:26.000Z",
  "employmentType": "FULL_TIME",
  "seniorityLevel": "Mid-Senior level",
  "jobFunction": null,
  "industry": "Automotive",
  "workplaceType": null,
  "applicantsCount": "Be among the first 25 applicants",
  "salary": "$91,000.00/yr - $120,000.00/yr",
  "salaryCurrency": "USD",
  "salaryMinValue": 91000,
  "salaryMaxValue": 120000,
  "salaryUnit": "YEAR",
  "experienceMonths": 72,
  "educationRequirement": "bachelor degree",
  "linkedinJobId": "4471214530",
  "jobId": "2373",
  "addressLocality": "Cornelius",
  "addressRegion": "NC",
  "addressCountry": "US",
  "latitude": 35.48491,
  "longitude": -80.85885,
  "description": "Summary\nThe Senior Development Engineer I requires knowledge of advanced engineering principles and methods related to tire design and analysis to meet target objectives. ...",
  "descriptionBullets": [
    "Summary",
    "The Senior Development Engineer I requires knowledge of advanced engineering principles and methods related to tire design and analysis to meet target objectives. ...",
    "Responsibilities",
    "Perform all types of development programs including for both replacement tire lines and original equipment customers."
  ],
  "jobUrl": "https://www.linkedin.com/jobs/view/senior-development-engineer-i-at-yokohama-tire-corporation-4471214530",
  "sourceUrl": "https://www.linkedin.com/jobs/view/senior-development-engineer-i-at-yokohama-tire-corporation-4471214530"
}
```

### Use cases

- **Job boards and aggregators** — feed fresh LinkedIn postings into your own board, filtered by role and location.
- **Recruiting and sales intelligence** — find companies hiring for specific roles as a buying signal.
- **Salary benchmarking** — collect posted pay ranges by title, seniority, and city.
- **Labor-market research** — track hiring volume by industry, job function, or region over time.
- **Job alerts** — schedule a daily run with **Date posted: Past 24 hours** and send new jobs to Slack or email.

### How much does it cost to scrape LinkedIn jobs?

LinkedIn Jobs Scraper uses pay-per-event pricing: you pay per job saved.

| Event | Free plan | Bronze | Silver | Gold |
|-------|-----------|--------|--------|------|
| `job-scraped` — per job | $0.00049 | $0.00044 | $0.00039 | $0.00034 |
| Per 1,000 jobs | **$0.49** | **$0.44** | **$0.39** | **$0.34** |

For example, 1,000 LinkedIn jobs on the Free plan cost $0.49. Use **Maximum jobs** or a [spending limit](https://docs.apify.com/platform/actors/running/usage-and-resources) to cap a run.

### Is it legal to scrape LinkedIn job postings?

LinkedIn Jobs Scraper reads only job postings that LinkedIn shows publicly to logged-out visitors. It does not log in, use cookies, or access private data. Job postings are business information published to attract applicants, but always check that your use complies with the laws and terms that apply to you, and consult a lawyer if in doubt. Read more in Apify's post [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

### Use LinkedIn Jobs Scraper with the API

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("parsebird/linkedin-jobs-scraper").call(run_input={
    "keywords": "data analyst",
    "location": "London",
    "datePosted": "pastWeek",
    "maxItems": 200,
})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["title"], job["company"], job.get("salary"))
```

**JavaScript**

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('parsebird/linkedin-jobs-scraper').call({
    keywords: 'nurse',
    location: 'Texas',
    experienceLevels: ['entryLevel', 'associate'],
    maxItems: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

See the [API tab](https://apify.com/parsebird/linkedin-jobs-scraper/api) for all endpoints and the [Apify API client docs](https://docs.apify.com/api/client/python) for more options.

### Other job scrapers

- [Indeed Jobs Scraper](https://apify.com/parsebird/indeed-jobs-scraper) — Indeed job postings in 60+ countries.
- [Dice Jobs Scraper](https://apify.com/parsebird/dice-jobs-scraper) — tech jobs from Dice.
- [Greenhouse Jobs Scraper](https://apify.com/parsebird/greenhouse-jobs-scraper) — jobs from Greenhouse company boards.
- [BuiltIn Jobs Scraper](https://apify.com/parsebird/builtin-jobs-scraper) — tech and startup jobs from Built In.

### FAQ

**Do I need a LinkedIn account or cookies?**
No. The actor uses LinkedIn's public job search and job pages that logged-out visitors can see.

**Do I need a proxy?**
No. Apify datacenter proxies are used automatically. A proxy you select is used only as a fallback for requests that stay blocked.

**How many jobs can one run collect?**
One LinkedIn search shows about 500 jobs. When you ask for more, the actor repeats the search over recent time windows (last hour, day, week, month, and so on) to reach more postings, up to 10,000 per run. Narrow searches may have fewer jobs than you ask for.

**Why do some jobs have the same `jobId`?**
`jobId` is the employer's own requisition ID. When one requisition is posted in several cities, each LinkedIn posting has its own `linkedinJobId` but they share the `jobId`.

**Why are salary or job function sometimes empty?**
LinkedIn shows them only when the employer provides them.

**Can I get new jobs every day?**
Yes. Schedule the actor with **Date posted: Past 24 hours** using [Apify schedules](https://docs.apify.com/platform/schedules).

**Why aren't there workplace-type or sort options?**
LinkedIn doesn't apply those for logged-out visitors. For remote jobs, enter `Remote` as the location.

**Are filtered-out jobs charged?**
No. With **Job type** or **Experience level** set, jobs that don't match are skipped and not charged.

**Something doesn't work?**
Open an issue on the [Issues tab](https://apify.com/parsebird/linkedin-jobs-scraper/issues) with your run link.

# Changelog

This Actor's version history is a separate document: https://apify.com/parsebird/linkedin-jobs-scraper/changelog.md

# Actor input Schema

## `keywords` (type: `string`):

Enter a job title or keywords, e.g. <code>software engineer</code>, <code>product manager</code>, <code>nurse</code>. Provide keywords, a location, or both.

## `location` (type: `string`):

Enter a city, region, or country, e.g. <code>San Francisco, CA</code>, <code>London</code>, <code>Germany</code>, or <code>Remote</code>. Leave empty to search worldwide.

## `maxItems` (type: `integer`):

Set how many job postings to collect. One LinkedIn search shows about 500 jobs; for larger runs the search is repeated over recent time windows to find more.

## `datePosted` (type: `string`):

Only include jobs posted within this period.

## `jobTypes` (type: `array`):

Only save jobs of these types. LinkedIn doesn't apply this filter for logged-out visitors, so each job is checked after it's read; only matching jobs are saved and charged. Leave empty for all.

## `experienceLevels` (type: `array`):

Only save jobs at these experience levels (LinkedIn's seniority level). Checked after each job is read; only matching jobs are saved and charged. Leave empty for all.

## `proxyConfiguration` (type: `object`):

Optional. The actor always starts on Apify datacenter proxies, which work for public LinkedIn job pages. A proxy you select here is only used as a fallback for requests that stay blocked.

## Actor input object example

```json
{
  "keywords": "software engineer",
  "location": "San Francisco, CA",
  "maxItems": 10,
  "datePosted": "any",
  "jobTypes": [],
  "experienceLevels": [],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keywords": "software engineer",
    "location": "San Francisco, CA",
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("parsebird/linkedin-jobs-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "keywords": "software engineer",
    "location": "San Francisco, CA",
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("parsebird/linkedin-jobs-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keywords": "software engineer",
  "location": "San Francisco, CA",
  "maxItems": 10
}' |
apify call parsebird/linkedin-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,parsebird/linkedin-jobs-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/StmlP1MJDHwKdhZMN/builds/J0izUyVf2lydWaVme/openapi.json
