# LinkedIn Hiring Tracker & Salary Intelligence (`scrapemint/linkedin-jobs-scraper`) Actor

Track LinkedIn hiring in real time. Every job row ships parsed salary range, tech stack, seniority tier, and remote type. Filter by keyword, location, experience, and post date. For comp researchers, recruiters, and M\&A scouts. JSON. Pay per job.

- **URL**: https://apify.com/scrapemint/linkedin-jobs-scraper.md
- **Developed by:** [Ken M](https://apify.com/scrapemint) (community)
- **Categories:** Automation, Lead generation, Social media
- **Features:** Limited permissions
- **Stats:** 25 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

$8.00 / 1,000 linkedin job rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Hiring Tracker & Salary Intelligence

Track LinkedIn hiring in real time. Every job row ships with a parsed salary range, a tech stack array, a seniority tier, a remote type, and minimum years of experience. No LinkedIn account or cookie needed. Clean JSON. Pay only for what you keep.

Built for compensation researchers, recruiters, M\&A scouts, business intelligence teams, and job aggregators who need structured LinkedIn hiring data without the Talent API or Sales Navigator seat cost.

**Ranks for:** LinkedIn hiring tracker, LinkedIn salary scraper, LinkedIn salary intelligence, LinkedIn comp research, LinkedIn jobs scraper, LinkedIn jobs API alternative, LinkedIn jobs API free, scrape LinkedIn jobs, LinkedIn jobs to CSV, LinkedIn jobs to JSON, tech stack extractor, LinkedIn recruiter intelligence, hiring velocity tracker, remote jobs scraper, LinkedIn guest jobs API.

***

### What makes this different

Most LinkedIn job scrapers dump raw title and description. This one computes the fields buyers actually want:

1. **Parsed salary range** on every job row. Currency, period (annual, monthly, weekly, daily, hourly), min, and max. Extracted from description text with sanity checks so "$50 gift card" does not pollute your dataset. Zero post processing.
2. **Tech stack extraction** on every engineering job. 120+ terms across languages, frameworks, cloud services, data stores, ML libraries, and dev tools. Returns a sorted deduped lowercase array. Built in. No extra cost.
3. **Seniority tier from title.** Maps messy LinkedIn titles to one of ten buckets (intern, entry, mid, senior, staff, lead, manager, director, vp, c-suite) so you can rank roles across companies without cleaning strings yourself.

***

### How it works

```mermaid
flowchart LR
    A[Keywords + locations] --> B[LinkedIn guest search<br/>/jobs-guest/api/seeMoreJobPostings]
    B --> C[Collect job IDs<br/>paginate]
    C --> D[Open each job detail<br/>/jobs-guest/api/jobPosting]
    D --> E[Parse title, company,<br/>description, criteria]
    E --> F[Compute salary, tech stack,<br/>seniority, remote type]
    F --> G[Push one row per job]
    G --> H[(JSON, CSV, Excel, API)]
```

No cookies, no login, no Sales Navigator seat. The actor hits LinkedIn's public guest endpoints the same way Google does when indexing jobs.

***

### Quick start

**Track new hiring at FAANG for the last week:**

```json
{
  "keywords": ["software engineer", "product manager", "data scientist"],
  "locations": ["San Francisco Bay Area", "New York", "Seattle"],
  "postedSince": "1w",
  "maxResults": 500
}
```

**Compensation benchmark for staff roles in California:**

```json
{
  "keywords": ["staff software engineer"],
  "locations": ["California, United States"],
  "experienceLevel": "mid-senior",
  "parseSalary": true,
  "maxResults": 200
}
```

**Remote only filter for agency sourcing:**

```json
{
  "keywords": ["backend engineer"],
  "locations": ["United States"],
  "remoteFilter": "remote",
  "postedSince": "1w",
  "maxResults": 100
}
```

**Competitor hiring watch (run daily on a schedule):**

```json
{
  "keywords": ["engineer at openai", "engineer at anthropic", "engineer at databricks"],
  "postedSince": "1d",
  "dedupe": true,
  "maxResults": 50
}
```

***

### Sample output

```json
{
  "id": "4406118990",
  "url": "https://www.linkedin.com/jobs/view/4406118990/",
  "title": "Staff Software Engineer, Platform",
  "company": "Stripe",
  "companyUrl": "https://www.linkedin.com/company/stripe",
  "location": "San Francisco, CA",
  "remote": "hybrid",
  "postedAgo": "2 days ago",
  "postedAt": "2026-04-22T14:00:00.000Z",
  "applicants": 42,
  "seniorityLevel": "Mid-Senior level",
  "employmentType": "Full-time",
  "jobFunction": "Engineering and Information Technology",
  "industries": "Financial Services",
  "seniorityTier": "staff",
  "salaryMin": 224000,
  "salaryMax": 330000,
  "salaryCurrency": "USD",
  "salaryPeriod": "annual",
  "techStack": ["aws", "go", "grpc", "kafka", "kubernetes", "postgresql", "python", "terraform"],
  "experienceYearsMin": 8,
  "applyUrl": "https://stripe.com/jobs/listing/...",
  "description": "About the role: Stripe's Platform team builds...",
  "descriptionLength": 4820,
  "scrapedAt": "2026-04-25T10:00:00.000Z"
}
```

***

### What you get per row

```mermaid
flowchart LR
    V[Job row] --> V1[Identity<br/>id, url, applyUrl]
    V --> V2[Posting<br/>title, company,<br/>location, postedAt]
    V --> V3[LinkedIn criteria<br/>seniorityLevel, type,<br/>function, industries]
    V --> V4[Computed signals<br/>salary, techStack,<br/>seniorityTier, remote,<br/>experienceYearsMin]
    V --> V5[Description<br/>cleaned text +<br/>length]
```

***

### Who uses this

| Role | Use case |
|---|---|
| Recruiter | Find open reqs at target companies with inferred tech stack for better candidate pitches. |
| Compensation research | Benchmark pay bands by title, seniority tier, geography, and tech stack across thousands of jobs. |
| M\&A scout | Track hiring velocity at private companies as a growth signal before the round hits the news. |
| Sales prospecting | Spot companies hiring roles that imply need for your product (e.g. Snowflake hiring = DW migration in progress). |
| Job aggregator | Build your own board with clean structured data and computed signals most scrapers do not ship. |
| Market researcher | Measure demand shifts for specific tech stacks and seniority tiers over time. |
| Founder | Watch your competitor's hiring page turn into a data feed. |

***

### Input reference

| Field | Type | Purpose |
|---|---|---|
| `keywords` | string\[] | Job search terms. One query per item. Required. |
| `locations` | string\[] | Locations to filter. Each location combines with each keyword. |
| `experienceLevel` | enum | internship, entry, associate, mid-senior, director, executive. |
| `jobType` | enum | full-time, part-time, contract, temporary, volunteer, internship, other. |
| `remoteFilter` | enum | onsite, remote, hybrid. |
| `postedSince` | enum | 1d, 1w, 1m. |
| `maxResults` | integer | Hard cap across all queries. LinkedIn exposes roughly 1000 per search. |
| `parseSalary` | boolean | Extract min, max, currency, period from the description text. |
| `extractTechStack` | boolean | Scan description for 120+ tech terms. |
| `classifySeniority` | boolean | Map title to an intern, entry, mid, senior, staff, lead, manager, director, vp, c-suite bucket. |
| `dedupe` | boolean | Skip job IDs from previous runs. |
| `proxyConfiguration` | object | Apify proxy. Residential recommended for runs above a few hundred jobs. |

***

### API example

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/YOUR_USER~linkedin-jobs-scraper/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "keywords": ["staff software engineer"],
    "locations": ["California, United States"],
    "postedSince": "1w",
    "maxResults": 200
  }'
```

***

### How this compares

|  | Official LinkedIn Talent API | Generic LinkedIn scrapers | Compensation data vendors | **This actor** |
|---|---|---|---|---|
| Access | Partner approval + $$$ | Often needs your LinkedIn cookie | Per seat license | Anyone, no cookie |
| Salary parsed | N/A | No | Yes | Yes, built in |
| Tech stack extraction | No | No | No | Yes, built in |
| Seniority classification | Raw LinkedIn label | Raw LinkedIn label | Proprietary taxonomy | Title based, 10 tiers |
| Remote type | No | Raw filter | Sometimes | Inferred from text |
| Cost model | Enterprise contract | Per run | Seat license | Pay per job row |
| Setup time | Months | Hours | Days | 60 seconds |

***

### Pricing

First 2 jobs per run are free so you can try before paying. After that you pay per result row. Salary parsing, tech stack extraction, seniority classification, remote inference, and experience year parsing are included at no extra cost.

***

### FAQ

**Is there a free LinkedIn jobs API?**
LinkedIn's Talent API is gated behind a partner agreement and a per seat contract. This actor gives anyone public LinkedIn job data with pay per use and no approval needed.

**Do I need a LinkedIn account or cookie?**
No. The actor uses LinkedIn's public guest endpoints, the same ones Google uses when indexing jobs.

**How accurate is the salary parser?**
High precision on jobs that publish a range in the description (mandatory under California, New York, Washington, and Colorado pay transparency laws). Handles USD, EUR, GBP, CAD, AUD, INR, and CHF. Plausibility checks reject outliers so small dollar amounts in the description do not get mistaken for pay. Jobs without a published range return `salaryMin: null`.

**How does the tech stack extractor work?**
A curated list of 120+ languages, frameworks, cloud services, data stores, ML libraries, and dev tools is scanned against the description with strict word boundary matching. C++ and C# are handled correctly. False positives from English words (go, rest, r) are filtered out.

**How accurate is seniority classification?**
Title based. Senior, staff, principal, lead, manager, director, vp, chief, and intern patterns are recognized. Default bucket is mid. This is meant as a fast normalizer across noisy LinkedIn labels, not a legal determination.

**Why is `salaryMin` null on some rows?**
Either the description did not publish a range, the range fell outside plausibility checks, or the job is in a jurisdiction with no pay transparency law. Turn on `parseSalary` and inspect `descriptionLength` to confirm.

**Can I paginate past 1000 results?**
LinkedIn's guest search caps at about 1000 jobs per query. Split your search into narrower filters (per city instead of per country, per experience level) to reach more jobs.

**Does it work for LinkedIn jobs in any country?**
Yes. Pass the location as LinkedIn spells it in its location dropdown. The actor ships with residential proxy rotation so your results reflect what a signed out visitor sees.

**Is scraping LinkedIn allowed?**
This actor reads public HTML any web visitor can see. Respect LinkedIn's terms and rate limit sensibly. Do not redistribute descriptions or company data you do not have the right to republish.

**Can I run this on a schedule?**
Yes. Use the Apify scheduler for hourly, daily, or weekly runs. Turn `dedupe` on to only push new job IDs. Great for competitor hiring watch and alerting.

***

### Related actors

- **Instagram Influencer Analyzer & Sponsored Post Tracker** for creator engagement rate and paid partnership detection
- **Reddit Lead Monitor: Subreddit and Keyword Alert Feed** for subreddit mentions and high intent leads
- **Google Maps Scraper** for local business data and reviews
- **Upwork Opportunity Alert** for freelance project leads

# Actor input Schema

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

One or more job search queries. Each query runs as a separate search. Examples: 'software engineer', 'product manager', 'data scientist'.

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

Locations to filter. Each location combines with each keyword. Use the spelling LinkedIn accepts, e.g. 'United States', 'London, United Kingdom', 'Remote'. Leave empty for worldwide.

## `experienceLevel` (type: `string`):

Filter by seniority as LinkedIn defines it. Leave blank for any.

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

Employment type. Leave blank for any.

## `remoteFilter` (type: `string`):

Restrict to on-site, remote, or hybrid roles.

## `postedSince` (type: `string`):

Only include jobs posted within this window.

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

Hard cap on jobs returned across all queries. LinkedIn exposes about 1000 results per search.

## `parseSalary` (type: `boolean`):

Extract salary range, currency, and period (annual, hourly, monthly) from the job description text. LinkedIn does not expose a structured salary field for most jobs. Built in. No extra cost.

## `extractTechStack` (type: `boolean`):

Scan the description for 120 common languages, frameworks, cloud services, and tools. Returns a deduped lowercase array. Built in. No extra cost.

## `classifySeniority` (type: `boolean`):

Map the job title to an intern, entry, mid, senior, staff, lead, manager, director, vp, or c-suite bucket. Useful for comp benchmarking across noisy LinkedIn labels. Built in. No extra cost.

## `dedupe` (type: `boolean`):

Skip job IDs already pushed in previous runs. Turn off to refresh stale rows. Off by default so a repeated query returns its full result set. Turn it on to poll for new items only.

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

Apify proxy. Datacenter works for LinkedIn guest endpoints at low volume. Use residential for runs above a few hundred jobs.

## Actor input object example

```json
{
  "keywords": [
    "software engineer"
  ],
  "locations": [
    "United States"
  ],
  "experienceLevel": "",
  "jobType": "",
  "remoteFilter": "",
  "postedSince": "",
  "maxResults": 100,
  "parseSalary": true,
  "extractTechStack": true,
  "classifySeniority": true,
  "dedupe": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

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

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

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

```

## MCP server setup

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