# LinkedIn Jobs Scraper: Remote Filter, Salaries & Job Alerts (`s_actors/linkedin-jobs-scraper`) Actor

Scrape LinkedIn jobs without login or cookies: full job pages, remote / hybrid / on-site, salaries found in job descriptions, job type, level, no reposts or staffing agencies, company jobs and new-job alerts. Export to Excel, CSV, JSON or n8n.

- **URL**: https://apify.com/s\_actors/linkedin-jobs-scraper.md
- **Developed by:** [Superior Actors](https://apify.com/s_actors) (community)
- **Categories:** Jobs, Lead generation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 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: Remote Filter, Salaries & Job Alerts

Scrape **LinkedIn jobs** to Excel, CSV or JSON **without login or cookies**: every job with its full job page, company, location, applicants, level, job type and description. On top of that, what other LinkedIn job scrapers stopped doing in 2026:

- **Remote / hybrid / on-site filter that works.** LinkedIn's new AI job search ignores the remote, job type, experience and salary filters for visitors, so scrapers that pass them to LinkedIn return every job. This Actor reads each job page and filters itself. **Filtered-out jobs are free.**
- **Salaries in 2 of 3 US jobs**, not only the 1 in 8 that fill LinkedIn's salary field: pay ranges are also read from the description (US pay-transparency ranges), converted to a year.
- **No reposts, no staffing agencies**, and **job alerts**: schedule it and get only the jobs you have not seen.

```json
{ "keywords": ["data engineer"], "locations": ["United States"], "workplaceTypes": ["remote"], "minYearlySalary": 120000 }
```

No LinkedIn account, no cookies, no browser extension. Use it as a **LinkedIn Jobs API**: one call returns clean JSON.

#### What you get

**One row per job.** Real example, September 2026 (data engineer, United States):

| job | company | location | remote / hybrid | salary | found in | posted | applicants | level |
|---|---|---|---|---|---|---|---|---|
| Senior Data Engineer, DX | Atlassian | Salt Lake City, UT | | $167,400 - $218,550 | description | 2026-09-26 | 200+ | Mid-Senior level |
| Data Engineer, Decision Intelligence Technology | Amazon Web Services (AWS) | Bellevue, WA | | 101,300 - 160,000 USD annually | description | 2026-09-23 | 125 | Not Applicable |
| Senior Data Engineer | NinjaOne | Georgia, United States | remote | $110,000 to $200,000 per year | description | 2026-09-24 | 57 | Not Applicable |
| Senior Data Engineer | fairlife | Chicago, IL | hybrid | $120,000 - $140,000 USD | description | 2026-09-23 | 200+ | Not Applicable |
| Product Manufacturing & Quality Engineer | OpenAI | San Francisco, CA | hybrid | $123,000/yr - $285,000/yr | LinkedIn | 2026-09-15 | 200+ | Not Applicable |

| Field | Description |
|---|---|
| `jobId`, `jobUrl`, `title` | The job and its LinkedIn link |
| `companyName`, `companyUrl`, `companyId`, `companyLogo` | The employer (`companyId` works in LinkedIn's company filter) |
| `location`, `postedDate`, `postedAgo` | Where and when (reposts show the repost date, as on LinkedIn) |
| `workplaceType`, `workplaceTypeSource`, `workplaceTypeEvidence` | `remote`, `hybrid`, `on-site` or empty when the job does not say; where it was found (`title`, `location`, `description`) and the exact words |
| `salaryText`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | Pay as posted: `hour`, `day`, `week`, `month` or `year` |
| `salaryYearlyMin`, `salaryYearlyMax`, `salarySource` | Pay converted to a year (hourly × 2 080); `linkedin` = LinkedIn's salary field, `description` = found in the job text |
| `applicants`, `applicantsText` | "Over 200 applicants" = 200; "Be among the first 25" = empty (fewer than 25) |
| `experienceLevel`, `employmentType`, `jobFunction`, `industries` | LinkedIn's job criteria, exact |
| `easyApply`, `isClosed`, `badge` | Easy Apply or the company's site; no longer accepting applications; "Actively Hiring", "Be an early applicant" |
| `description`, `descriptionHtml` | The full job description, plain text and / or HTML |
| `searchKeyword`, `searchLocation`, `searchUrl` | Which search found the job |
| `isNew`, `scrapedAt` | Job alerts: new since the last run |

Two table views: **Jobs** and **Salaries** (yearly min / max, currency, where the pay was found).

#### How it works

| Step | What happens |
|---|---|
| 1. Search | Each keyword in each location (or your pasted LinkedIn search links), with the filters LinkedIn still applies: date posted, company, Easy Apply, under 10 applicants. Up to 1 000 jobs per search, LinkedIn's limit |
| 2. Job pages | Every new job's public page: criteria, applicants, salary, description, company id, closed or open |
| 3. Filters | Remote / hybrid / on-site, job type, level, minimum yearly salary, staffing agencies, title words, companies. Jobs removed here are not charged |
| 4. Clean-up | The same job found by several searches appears once; reposts (same title, company and location) are skipped |
| 5. Job alerts | With **Only new jobs** on, jobs from earlier runs are skipped before their page is loaded |

Requests go through Apify Proxy, a fresh IP each time: LinkedIn limits one IP to about 15 requests, and a new IP per request passed 199 of 200 in our tests.

#### Why this Actor

| | This Actor | Typical LinkedIn job scraper |
|---|---|---|
| Remote / hybrid filter | ✅ Applied from the job text, with the evidence | ❌ Passed to LinkedIn, ignored since the 2026 AI search, or rewritten into keywords |
| Job type and experience level filters | ✅ Exact, from the job page | ⚠️ Ignored by LinkedIn or rewritten into keywords |
| Salary | ✅ LinkedIn's field + pay ranges in descriptions, yearly | ⚠️ LinkedIn's field only (about 1 US job in 8) |
| Minimum salary filter | ✅ Yearly, hourly pay converted | ❌ / ⚠️ LinkedIn's bands, ignored for visitors |
| Reposts and staffing agencies | ✅ Skipped, not charged | ⚠️ Some |
| Job alerts (only new jobs) | ✅ Built in, seen jobs not charged | ⚠️ Manual lists of job IDs |
| Company jobs by name or link | ✅ Name, link or id | ⚠️ Numeric id only |
| Filtered-out jobs | ✅ Free | ❌ Charged, or not filtered |
| Login or cookies | ✅ Not needed | ✅ / ⚠️ Some need your account |

#### Pricing

Pay per event, no subscription needed. Apify Scale and Business plans pay less:

| Event | Free and Starter plans | Scale plan | Business plan |
|---|---|---|---|
| Run start | $0.001 | $0.001 | $0.001 |
| Job (with its full job page) | $0.0005 | $0.00045 | $0.0004 |

**1 000 jobs = $0.50.** Free: jobs removed by your filters, reposts, jobs already seen by a job alert. Platform usage is included. Set a maximum cost per run in the run options: the Actor stops there.

#### Ready-made tasks

| Task | What it does |
|---|---|
| [LinkedIn Remote Jobs Scraper](https://apify.com/s_actors/linkedin-jobs-scraper/examples/linkedin-remote-jobs-scraper) | Remote-only jobs with salaries, reposts removed |
| [LinkedIn Job Alerts for a Company](https://apify.com/s_actors/linkedin-jobs-scraper/examples/linkedin-company-job-alerts) | Every new job of chosen companies, schedule it daily |
| [Export LinkedIn Jobs to Excel](https://apify.com/s_actors/linkedin-jobs-scraper/examples/export-linkedin-jobs-to-excel) | A job search to a spreadsheet with yearly salaries |

#### Job alerts

LinkedIn's own job alerts cannot filter by salary or remote work and often miss jobs. Build your own:

1. Set your search and filters, turn on **Only new jobs**, give the alert a **Monitor name**.
2. Save it as a task and add a **schedule** (every morning, or every hour with "Posted within: Past hour").
3. Send the results by email, Slack, Google Sheets, Make, Zapier or **n8n** with Apify integrations.

The first run returns the current jobs; next runs return only jobs not seen before. Seen jobs are skipped before their page is loaded and are not charged.

#### FAQ

**Why not use LinkedIn's own remote filter?** Since LinkedIn's 2026 AI job search, the remote (`f_WT`), job type (`f_JT`), experience (`f_E`) and salary (`f_SB2`) filters in a search link are ignored for visitors: the results are the same with or without them. We checked each of them in September 2026.

**How is remote work detected?** LinkedIn's public job page does not state it. The Actor looks at the title ("Senior Engineer (Remote)"), the location and clear phrases in the description ("this is a fully remote position", "hybrid role, 3 days a week in the office", "this is an on-site role"). Vague perks ("flexibility to work from home") do not count. `workplaceTypeEvidence` shows the words it used; jobs that do not say stay empty. In our test (100 US data engineer jobs, September 2026) 27 stated it clearly: 17 hybrid, 8 remote, 2 on-site. For remote-only lists, add "remote" to the keywords as well: LinkedIn then returns mostly remote jobs and the filter removes the rest.

**Can I get more than 1 000 jobs?** LinkedIn stops every search at 1 000. Split it: several locations (states or cities) or several keywords in one run. Jobs found twice are returned once.

**Why is the salary a range in a foreign currency?** Salaries stay in the job's currency; `salaryYearlyMin` / `salaryYearlyMax` convert hours, days and months to a year, not currencies.

**Do I need a LinkedIn account?** No. Only public job pages are read, as any visitor sees them.

**What does `isClosed` mean?** The job no longer accepts applications. Search results skip closed jobs; job links you paste are returned with `isClosed: true`.

#### Use with the API and AI agents

Run it from the Apify API, the JavaScript or Python client, **n8n**, Make or Zapier, or from AI agents through the [Apify MCP server](https://mcp.apify.com) (Claude, ChatGPT, Cursor). One call: `POST https://api.apify.com/v2/acts/s_actors~linkedin-jobs-scraper/run-sync-get-dataset-items` with the input above returns the jobs as JSON. Set **Job description** to "None" for smaller answers.

#### Is it legal?

The Actor reads public LinkedIn job pages that anyone can open without an account, as a visitor does. It does not log in or collect personal profiles. Use the data according to the laws that apply to you (GDPR and similar) and LinkedIn's terms.

# Actor input Schema

## `keywords` (type: `array`):

One per line, as in the LinkedIn search box: "data engineer", "registered nurse", "python OR golang". Each keyword is searched in each location. Leave empty to get all jobs in the locations.

## `locations` (type: `array`):

Country, state, city or region as LinkedIn understands it: "United States", "London, England, United Kingdom", "Germany", "Worldwide". Empty = Worldwide.

## `companies` (type: `array`):

Optional. Only jobs of these companies: a company name ("Stripe"), its LinkedIn page link (linkedin.com/company/openai) or its numeric id. With no keywords you get all open jobs of the company.

## `postedWithin` (type: `string`):

Only jobs posted (or reposted) in this period. Use "Past 24 hours" or "Past hour" for daily or hourly job alerts.

## `maxJobsPerSearch` (type: `integer`):

Per keyword and location (and per search link). LinkedIn shows at most 1 000 jobs per search: for more, add locations (cities or states).

## `workplaceTypes` (type: `array`):

Keep only jobs of these types. LinkedIn's public pages do not state it, so it is found in the title, location and description ("Remote", "hybrid role, 3 days a week in the office", "this is an on-site position"). Jobs that do not say are left out when this filter is on.

## `employmentTypes` (type: `array`):

Keep only these employment types (exact, from the job page).

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

Keep only these seniority levels (exact, from the job page). Many large employers leave it "Not Applicable": add "Not stated" to keep them.

## `minYearlySalary` (type: `integer`):

Keep only jobs whose salary range reaches this amount per year, in the job's currency (hourly and monthly pay are converted to a year). Implies "Only jobs with salary".

## `onlyWithSalary` (type: `boolean`):

Keep only jobs with a salary: LinkedIn's salary field or a pay range found in the description (US pay-transparency ranges).

## `easyApplyOnly` (type: `boolean`):

Only jobs you can apply to on LinkedIn (applied by LinkedIn itself).

## `under10Applicants` (type: `boolean`):

Only jobs with under 10 applicants so far (applied by LinkedIn itself).

## `excludeStaffingAgencies` (type: `boolean`):

Skip jobs posted by staffing and recruiting companies (industry "Staffing and Recruiting").

## `titleInclude` (type: `array`):

Keep only jobs whose title contains one of these words (case-insensitive), e.g. "senior", "lead".

## `titleExclude` (type: `array`):

Skip jobs whose title contains one of these words, e.g. "intern", "manager", "sales".

## `companyExclude` (type: `array`):

Skip jobs of companies whose name contains one of these words.

## `skipDuplicates` (type: `boolean`):

A job with the same title, company and location as one already in the results (reposts and copies) is skipped and not charged.

## `onlyNewJobs` (type: `boolean`):

Return only jobs not returned by earlier runs with the same monitor name. The first run returns the current jobs.

## `monitorName` (type: `string`):

Separate job alert lists: runs with the same name share the jobs already seen.

## `searchUrls` (type: `array`):

linkedin.com/jobs/search/?keywords=...\&location=... links copied from your browser. Keywords, location, date posted, company, Easy Apply and under-10-applicants are taken from the link; use the filters above for remote, job type, level and salary.

## `jobUrls` (type: `array`):

Full details of specific jobs: linkedin.com/jobs/view/... links, links with currentJobId=..., or job IDs. Closed jobs are returned too, with isClosed = true.

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

Format of the job description field.

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

Keep Apify Proxy (datacenter) on: each request goes from a fresh IP. LinkedIn limits one IP to a few requests.

## `maxConcurrency` (type: `integer`):

How many LinkedIn pages are loaded at once.

## `debugLog` (type: `boolean`):

Log every failed attempt.

## Actor input object example

```json
{
  "keywords": [
    "data engineer"
  ],
  "locations": [
    "United States"
  ],
  "postedWithin": "anyTime",
  "maxJobsPerSearch": 100,
  "onlyWithSalary": false,
  "easyApplyOnly": false,
  "under10Applicants": false,
  "excludeStaffingAgencies": false,
  "skipDuplicates": true,
  "onlyNewJobs": false,
  "monitorName": "default",
  "descriptionFormat": "text",
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 10,
  "debugLog": false
}
```

# Actor output Schema

## `overview` (type: `string`):

The main job fields.

## `salaries` (type: `string`):

Pay ranges converted to a year.

## `all` (type: `string`):

Every field of every job.

# 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": [
        "data engineer"
    ],
    "locations": [
        "United States"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("s_actors/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": ["data engineer"],
    "locations": ["United States"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("s_actors/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": [
    "data engineer"
  ],
  "locations": [
    "United States"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call s_actors/linkedin-jobs-scraper --silent --output-dataset

```

## MCP server setup

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