# Linkedin Jobs Scraper (`openclawai/linkedin-jobs-scraper`) Actor

Scrape LinkedIn jobs - Search by keyword, location, company, salary, posted-date, remote, easy-apply. Full descriptions, salary range, direct apply URLs. Multi-keyword search, auto-deduplication, pay only for results. No API key

- **URL**: https://apify.com/openclawai/linkedin-jobs-scraper.md
- **Developed by:** [Pika Choo](https://apify.com/openclawai) (community)
- **Categories:** Jobs, Lead generation, Integrations
- **Stats:** 387 total users, 36 monthly users, 100.0% runs succeeded, 5 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.50 / 1,000 job scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## LinkedIn Jobs Scraper — Jobs, Salaries & Companies at $0.0005/job

Scrape LinkedIn job listings for **$0.0005 per job ($0.50 per 1,000 jobs)**. Search by keyword, location, company, posted date, job type, remote and Easy Apply, then get clean JSON, CSV or Excel with title, company, location, salary range, direct apply URL and the full description. No LinkedIn login, no API key, and you only pay for jobs that actually land in your dataset.

This is the fast, budget tier of our LinkedIn job scrapers. If you need per-URL scraping of individual postings or LinkedIn search URLs with deeper company enrichment, use our premium LinkedIn Jobs Scraper at $0.04/job. If you want the most listings per dollar from keyword searches, this is the one.

### Who uses this LinkedIn jobs scraper?

- **Recruiters and staffing agencies** tracking open roles at target companies and spotting hiring trends before competitors do.
- **Job boards and aggregators** that need a fresh feed of LinkedIn jobs by keyword and region, deduplicated and ready to publish.
- **Sales and lead generation teams** who treat a new job posting as a buying signal (a company hiring a Head of Data probably needs data tools).
- **Market researchers and analysts** studying salary ranges, remote work share and demand for skills by city or industry.
- **Job seekers and career coaches** building a daily digest of new listings that match a title, radius and posted-within window.
- **AI agents and data pipelines** that need structured job data on demand through the Apify API or MCP.

### What you get: LinkedIn job data fields

Every row in the dataset is one LinkedIn job listing. Fields are omitted from a row when LinkedIn did not provide them.

| Field | Description |
|---|---|
| `id` | Unique LinkedIn job identifier |
| `title` | Job title as posted |
| `company` | Hiring company name |
| `location` | City, state and country string |
| `job_url` | URL of the LinkedIn job posting |
| `job_url_direct` | Direct application URL on the company website (needs Fetch Full Descriptions) |
| `description` | Full job description in Markdown or HTML (needs Fetch Full Descriptions) |
| `salary_min`, `salary_max` | Salary range when LinkedIn shows one |
| `salary_currency`, `salary_interval` | Currency code and interval (yearly, monthly, hourly) |
| `salary_source` | Where the salary came from (`direct_data` when posted by the employer) |
| `job_type` | fulltime, parttime, contract, internship or temporary |
| `is_remote` | `true` when the listing is remote |
| `date_posted` | Posting date in ISO format |
| `job_level`, `job_function`, `listing_type` | Seniority, function and listing type when available |
| `company_industry`, `company_url`, `company_url_direct`, `company_logo`, `banner_photo_url` | Company metadata |
| `emails` | Email addresses found in the description, comma separated |
| `skills`, `experience_range`, `vacancy_count`, `work_from_home_type` | Extra attributes when LinkedIn exposes them |
| `search_term`, `matched_search_term` | The query that surfaced this row (useful with multi-keyword runs) |
| `scraped_at` | UTC timestamp of the run |

### How to run it: inputs and search modes

You can search with one keyword or up to five at once. Multi-keyword runs are merged and deduplicated so the same job listed under two queries is billed once.

| Field | Type | Description |
|---|---|---|
| `searchTerm` | string | Job title or keyword (e.g. `"software engineer"`) |
| `searchTerms` | array (max 5) | Multiple queries merged into one dataset |
| `location` | string | City, state, or country (e.g. `"New York, NY"`). Empty = worldwide |
| `maxResults` | int (1 to 5000) | Max jobs per search term (default 50) |
| `isRemote` | bool | Remote-only filter |
| `jobType` | enum | fulltime / parttime / contract / internship / temporary |
| `hoursOld` | int | Only jobs posted within the last N hours (24 = last day, 168 = last week) |
| `distance` | int | Search radius in miles from the location |
| `offset` | int | Skip the first N results for pagination |
| `easyApply` | bool | One-click apply jobs only |
| `linkedinFetchDescription` | bool | Fetch the full description and direct apply URL (slower, richer) |
| `linkedinCompanyIds` | array | Restrict the search to specific LinkedIn company IDs |
| `descriptionFormat` | enum | `markdown` (default) or `html` |
| `enforceAnnualSalary` | bool | Convert hourly and monthly pay to annual |
| `proxyConfiguration` | object | Apify proxy (residential recommended) |

Example input:

```json
{
  "searchTerms": ["data engineer", "analytics engineer"],
  "location": "Berlin, Germany",
  "maxResults": 200,
  "hoursOld": 168,
  "isRemote": false,
  "linkedinFetchDescription": true,
  "enforceAnnualSalary": true
}
```

### How much does it cost to scrape 1,000 LinkedIn jobs?

Pricing is pay per event. You are billed for jobs delivered to the dataset, never for failed requests, retries or empty searches.

| Event | Price |
|---|---|
| `job-scraped` (per LinkedIn job returned) | **$0.0005** |
| Dataset item (Apify platform fee per stored row) | $0.00001 |
| Actor start (once per run, per GB of memory) | $0.00005 |

Scheduled change: from September 11, 2026 the price is $0.005 per job ($5 per 1,000).

Worked example for 1,000 jobs on the default 1 GB memory:

- 1,000 × $0.0005 = **$0.50** for the jobs
- 1,000 × $0.00001 = $0.01 in dataset storage
- 1 × $0.00005 for the run start
- **Total: about $0.51**

So 100 jobs cost about $0.05, 1,000 jobs about $0.50, and 10,000 jobs about $5. Set the `ACTOR_MAX_TOTAL_CHARGE_USD` environment variable (or the spending limit in the Console run options) to hard-cap a run; the scraper reads the cap and truncates the output instead of overspending.

### Sample output

A single dataset row with full description fetching enabled looks like this:

```json
{
  "id": "4012345678",
  "title": "Senior Software Engineer",
  "company": "JPMorganChase",
  "location": "New York, NY, US",
  "job_url": "https://www.linkedin.com/jobs/view/4012345678",
  "job_url_direct": "https://careers.example.com/jobs/4012345678",
  "site": "linkedin",
  "job_type": "fulltime",
  "is_remote": false,
  "date_posted": "2026-04-01",
  "salary_source": "direct_data",
  "salary_min": 120000,
  "salary_max": 185000,
  "salary_currency": "USD",
  "salary_interval": "yearly",
  "job_level": "Mid-Senior level",
  "job_function": "Engineering",
  "company_industry": "Financial Services",
  "company_url": "https://www.linkedin.com/company/jpmorganchase",
  "company_logo": "https://media.licdn.com/dms/image/.../logo.png",
  "description": "## About the role\n\nWe are looking for a Senior Software Engineer to join ...",
  "search_term": "software engineer",
  "matched_search_term": "software engineer",
  "scraped_at": "2026-08-29T16:30:00+00:00"
}
```

Download the whole dataset as JSON, CSV, Excel, XML or RSS from the run page or with one API call.

### Frequently asked questions

#### Does LinkedIn have an official jobs API?

LinkedIn does not offer a public jobs search API. The official Talent Solutions and Job Posting APIs are limited to approved partners and are built for posting jobs, not for reading them. This scraper reads public job listings the same way a logged-out browser does and returns them as structured data, so you can search LinkedIn jobs programmatically without a partnership or an API key.

#### Do I need a LinkedIn account or API key?

No. The scraper works on public listings without logging in, so your personal LinkedIn account is never involved and cannot be restricted. You only need an Apify account.

#### How fast is it and are there limits?

A 50-job search usually finishes in under a minute. Runs of 1,000 or more jobs typically take 10 minutes or longer because LinkedIn paginates results and throttles aggressive traffic; raise the run timeout to 3,600 seconds for large sweeps. Each search term can return up to 5,000 jobs and a run can combine up to 5 terms, so one run can deliver up to 25,000 listings. LinkedIn may return fewer results than requested for narrow queries, and you are only charged for what is delivered.

#### Why do I get fewer jobs than maxResults or zero results?

LinkedIn rate-limits IP addresses after roughly 50 to 100 results per session. Use the default Apify residential proxy group for anything above a handful of pages; the scraper rotates to a fresh IP on each retry automatically. Very narrow filters (for example a small radius plus a short `hoursOld` window) can also return few jobs. Combining `hoursOld` with `easyApply` is not supported on LinkedIn's side, so the scraper drops `easyApply` and warns in the log.

#### Can I scrape jobs from specific companies only?

Yes. Pass one or more LinkedIn company IDs in `linkedinCompanyIds` and the search is restricted to those employers. Combine with `hoursOld` to monitor a watchlist of companies for new openings every day.

#### Which output formats are supported?

Results are stored in an Apify dataset and can be exported as JSON, CSV, Excel, XML, HTML table or RSS. Descriptions are returned as Markdown by default, or HTML if you set `descriptionFormat` to `html`.

#### How does this compare to the $0.04/job LinkedIn Jobs Scraper?

This actor is optimised for keyword and location searches at the lowest cost per listing. The premium actor adds scraping by individual job URL and by LinkedIn search URL, at a much higher price per job. Start here for bulk discovery and monitoring, and move up when you need per-URL detail.

#### Is it legal to scrape LinkedIn jobs?

Scraping publicly available data is generally lawful in many jurisdictions, and job postings are published so that people can find them. You are responsible for how you use the data: respect LinkedIn's terms, applicable privacy laws such as GDPR and CCPA, and avoid storing personal data you do not need. Job listings are business information about employers, not private profile data.

### Use with AI agents and MCP

The actor is available as a tool through the Apify MCP server, so Claude, ChatGPT, Cursor and other MCP-capable agents can search LinkedIn jobs on demand:

```
https://mcp.apify.com/?tools=fetch-actor-details,openclawai/linkedin-jobs-scraper
```

Add that URL as an MCP server with your Apify token and ask the agent, for example, to "find remote data engineer jobs posted in the last 24 hours and summarise the salary ranges". A step-by-step guide with prompt examples is available on Datapika: https://datapika.com/actors/linkedin-jobs-scraper

### Integrations: API, Python, JavaScript and automation

- **REST API**: start a run with `POST https://api.apify.com/v2/acts/openclawai~linkedin-jobs-scraper/runs` and read the dataset from `GET /v2/datasets/{datasetId}/items?format=json`.
- **Python**: `pip install apify-client`, then `ApifyClient(token).actor("openclawai/linkedin-jobs-scraper").call(run_input={...})`.
- **JavaScript / Node.js**: `npm i apify-client`, then `new ApifyClient({ token }).actor("openclawai/linkedin-jobs-scraper").call({...})`.
- **Scheduling and webhooks**: schedule the actor in Apify Console (for example every morning with `hoursOld: 24`) and use a webhook to push new rows to your own endpoint.
- **No-code**: connect through Apify's Zapier, Make, n8n, Google Sheets and Airtable integrations to route new jobs into a spreadsheet, CRM or Slack channel.

### Tips for reliable LinkedIn scraping

- Keep the default residential proxy for any run above 100 jobs; datacenter IPs are blocked quickly.
- Use `offset` to page through large result sets across several runs instead of one very long run.
- Turn on `linkedinFetchDescription` only when you need the body text or the direct apply URL; it roughly doubles run time.
- Use `enforceAnnualSalary` when comparing hourly and salaried roles in the same dataset.
- Watch the run log: per-term retry attempts, deduplication counts and any spending-cap truncation are printed there.

### Legal and responsible use

This actor collects publicly visible job listings only. It does not log in, does not access private profiles and does not bypass authentication. Use the data in line with LinkedIn's terms of service and the data protection laws that apply to you, and do not use it to spam candidates or employers. If you are unsure about a particular use case, consult a lawyer.

# Actor input Schema

## `searchTerm` (type: `string`):

Job title, keyword, or skill to search for (e.g. "software engineer", "data analyst").

## `searchTerms` (type: `array`):

Run up to 5 queries in one go — results are merged and deduplicated. Each row is tagged with the term that surfaced it. Cost scales linearly. Leave empty to use the single Search Term above.

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

City, state, or country (e.g. "New York, NY", "London", "Remote"). Leave empty to search globally.

## `maxResults` (type: `integer`):

Maximum jobs to return per search term (1–5000). LinkedIn rate-limits residential IPs after ~50 results, so default is conservative. Large runs (>500) may take 10+ minutes and rotate proxy sessions automatically.

## `isRemote` (type: `boolean`):

Return only remote job listings.

## `jobType` (type: `string`):

Filter by employment type.

## `hoursOld` (type: `integer`):

Only return jobs posted within the last N hours (24 = last day, 168 = last week). Cannot be combined with Easy Apply.

## `distance` (type: `integer`):

Search radius in miles from the location. Use 0 for exact location only.

## `offset` (type: `integer`):

Skip the first N results — useful for paginating large result sets.

## `easyApply` (type: `boolean`):

Return only one-click apply jobs. Cannot be combined with Posted Within.

## `linkedinFetchDescription` (type: `boolean`):

Fetch the full job description and direct apply URL for each posting. Slower but richer output.

## `linkedinCompanyIds` (type: `array`):

Restrict the search to specific companies by their LinkedIn company ID (e.g. \["1441", "2382910"]). Leave empty to search all companies.

## `descriptionFormat` (type: `string`):

Format for description text in the output.

## `enforceAnnualSalary` (type: `boolean`):

Convert hourly/monthly salaries to annual equivalents for easier comparison.

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

Residential proxies recommended — LinkedIn rate-limits IPs after ~100 results.

## Actor input object example

```json
{
  "searchTerm": "software engineer",
  "location": "New York, NY",
  "maxResults": 50,
  "isRemote": false,
  "jobType": "",
  "distance": 50,
  "easyApply": false,
  "linkedinFetchDescription": false,
  "descriptionFormat": "markdown",
  "enforceAnnualSalary": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (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 = {
    "searchTerm": "software engineer"
};

// Run the Actor and wait for it to finish
const run = await client.actor("openclawai/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 = { "searchTerm": "software engineer" }

# Run the Actor and wait for it to finish
run = client.actor("openclawai/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 '{
  "searchTerm": "software engineer"
}' |
apify call openclawai/linkedin-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,openclawai/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/MdN03OuWoamJICdrR/builds/ZTcHc8WzCvHVNNwYC/openapi.json
