# LinkedIn Jobs Scraper + Glassdoor (Salary, Skills) (`molded_mountainpass/linkedin-glassdoor-jobs-scraper`) Actor

Scrape LinkedIn jobs and Glassdoor jobs in one run into one clean, deduplicated dataset: title, company, location, salary, skills, company rating and apply link. No login, no cookies, no browser. Daily "only new jobs" mode. Export JSON, CSV or Excel. From $0.40 per 1,000 jobs.

- **URL**: https://apify.com/molded_mountainpass/linkedin-glassdoor-jobs-scraper.md
- **Developed by:** [Divya Raj](https://apify.com/molded_mountainpass) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 4.90 out of 5 stars

## Pricing

Pay per event

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 + Glassdoor: one dataset, with salaries and skills

Scrape **LinkedIn jobs and Glassdoor jobs** in a single run and get back **one clean,
deduplicated dataset**: same field names and shapes, whichever site a job came from. Every
listing has title, company, location, posted date and job link. Glassdoor listings add salary
(~76%), skills and company rating. With full details on, LinkedIn jobs get skills (~99%) and pay
(about half of US postings) read from the job description. Export as JSON, CSV or Excel, or pull it through the API.

No login, no cookies, no browser. It sends plain HTTP requests, which is why it is fast and
costs a fraction of what browser-based job scrapers charge. **From $0.40 per 1,000 jobs.**

**~850 LinkedIn jobs in 87 seconds. 500 Glassdoor jobs in 10 seconds.**

***

### Why this one

Most job scrapers on the Store do a single site. Running two of them gets you two different
schemas, two sets of duplicates and two bills.

| | This Actor |
|---|---|
| Sites per run | **LinkedIn + Glassdoor** |
| Output schema | **one unified schema** |
| Duplicates across sites | **removed** |
| Salary | **Glassdoor: ~76% of listings.** LinkedIn with `fetchDetails`: ~50% in the US, ~10% in India, read from the description |
| Skills | **Glassdoor: 100% of listings.** LinkedIn with `fetchDetails`: ~99%, read from the description |
| Company ratings | **Glassdoor** |
| "Only new jobs" mode for schedules | **yes** |
| Price per 1,000 jobs | **from $0.40, no start fee** |

The two sites complement each other: LinkedIn brings volume and full job descriptions, Glassdoor
brings salary, skills and employer ratings. LinkedIn's public pages have no skills field and rarely
a salary field, so with `fetchDetails` on the Actor reads both from the job description.

### Who uses it

- **Recruiters and staffing agencies**: find every company hiring for a role in a city, with
  salary ranges to pitch against.
- **Job boards and job-alert apps**: a daily feed of fresh postings from two sources in one
  schema, with `onlyNewJobs` so you never pay twice for the same job.
- **Salary and labour-market research**: Glassdoor pay ranges and skills by title, location
  and company.
- **Sales and lead generation**: companies that are hiring are companies with budget.
- **AI agents and LLM apps**: structured job data through the Apify API or the Apify MCP
  server.

### How to scrape LinkedIn and Glassdoor jobs

1. Enter one or more **keywords** (e.g. `data analyst`) and **locations** (e.g. `India`,
   `London`, `Remote`), or paste a LinkedIn or Glassdoor search URL.
2. Pick the **sources**, how many jobs you want, and how recent (`24h`, `week`, `month`).
3. Click **Start**. Download the results as JSON, CSV or Excel, or fetch them through the API.

### What you get for every job

Every field is always present — unknown values are `null`, never missing — so CSV and Excel
exports keep stable columns.

| Group | Fields |
|---|---|
| Identity | `id`, `source`, `sourceJobId`, `url`, `applyUrl` |
| Role | `title`, `description`, `descriptionHtml`, `jobFunction`, `industry` |
| Company | `company`, `companyUrl`, `companyLogo`, `companyRating`, and with `fetchDetails`: `companySize`, `companyEmployees`, `companyIndustry`, `companyWebsite`, `companyDescription`, `companyFounded`, `companyAddress` |
| Place & type | `location`, `workType` (remote / hybrid / on-site), `jobType` |
| Pay | `salary.min`, `.max`, `.currency`, `.period`, `.raw`, `.source` |
| Experience | `experienceLevel`, `experienceYears.min`, `experienceYears.max` |
| Skills | `skills[]` |
| Timing & signals | `postedAt`, `postedAtRaw`, `applicants`, `easyApply`, `activelyHiring`, `earlyApplicant` |
| Provenance | `searchKeyword`, `searchLocation`, `detailsFetched`, `scrapedAt` |

`salary.source` says where a figure came from: `EMPLOYER_PROVIDED` or `ESTIMATED` (Glassdoor), or
`description` when it was read from the job text, so you can filter down to the pay you trust.

#### Example output

```json
{
  "id": "glassdoor:1010260754808",
  "source": "glassdoor",
  "title": "Mid-Level Developer – AI-Enabled Systems (Remote, India)",
  "company": "Best Access Doors",
  "companyUrl": "https://www.glassdoor.com/Overview/-EI_IE3727326.htm",
  "companyRating": 4.6,
  "location": "Bengaluru",
  "workType": "remote",
  "salary": {
    "min": 360000,
    "max": 760000,
    "currency": "INR",
    "period": "year",
    "raw": "INR 360,000 - INR 760,000 per year",
    "source": "ESTIMATED"
  },
  "skills": ["Authentication", "Technical troubleshooting", "Systems integration"],
  "postedAt": "2026-09-12T18:44:42.083Z",
  "postedAtRaw": "29d",
  "easyApply": false,
  "jobFunction": "it engineer",
  "searchKeyword": "react developer",
  "searchLocation": "India"
}
```

### Pricing

Pay per result. You are charged for jobs you actually receive, nothing else.

| Event | What it is | Free plan | Bronze | Silver | Gold and up |
|---|---|---|---|---|---|
| `job` | title, company, location, salary when shown, skills, rating, posted date, link | **$0.40** | $0.36 | $0.32 | **$0.30** |
| `job-with-details` | all of the above plus the full description, applicant count, seniority and industry | **$1.20** | $1.08 | $0.96 | **$0.90** |

Prices are per 1,000 jobs. No start fee, no monthly rent.

Set a **max cost per run** in the run options and the Actor stops the moment it is reached, so it
never overshoots your budget.

### Two ways to search

**1. Keywords and locations.** Every keyword is searched in every location.

```json
{
  "keywords": ["react developer", "python developer"],
  "locations": ["India", "Bangalore"],
  "sources": ["linkedin", "glassdoor"],
  "maxItemsPerSource": 500,
  "postedWithin": "week",
  "fetchDetails": false
}
```

**2. Paste a search URL.** Build the search on LinkedIn or Glassdoor with whatever filters you
like and paste the URL. Each URL runs only against the site it came from.

```json
{
  "startUrls": [
    "https://www.linkedin.com/jobs/search?keywords=react%20developer&location=India",
    "https://www.glassdoor.com/Job/bengaluru-react-developer-jobs-SRCH_IL.0,9_IC2940587_KO10,25.htm"
  ]
}
```

#### Options worth knowing

- **`fetchDetails`** — everything about the job and the employer: full description, applicants,
  seniority, skills and salary, plus company size, employee count, address, website and
  description. Priced as a detailed job. Off by default: basic is cheaper and faster.
- **`onlyEarlyApplicants`** — LinkedIn jobs marked "Be an early applicant", so you apply before
  the crowd. LinkedIn applies it itself. (LinkedIn's public pages show "first 25 applicants" at
  best, so no scraper can honestly promise an exact "under 10".)
- **`onlyNewJobs`** — remembers every job id already returned to you and skips it next time.
  Ideal with a daily schedule: you only pay for jobs you have not seen.
- **`dedupeAcrossSources`** — when the same role is posted on both sites, return it once.
- **`postedWithin`** — `24h`, `week`, `month` or `any`.
- **`minCompanyRating`, `companySize`, `searchRadius`** — Glassdoor's own filters: employer rating
  (1.0+ to 4.0+), company size (1-200 up to 5,001+ employees) and miles around a city. Glassdoor
  applies them before results come back, so they cost nothing extra. LinkedIn has no equivalent.
- **`maxItemsPerSource`** — hard stop per site.

### Speed, and the limits worth knowing

Better said up front than discovered later.

- **LinkedIn returns ~854–868 unique jobs per keyword + location**, because its public search caps
  a query at roughly 1,000 results. Use more keywords or locations to go wider.
- **Glassdoor reports how many jobs a search has** (often thousands) and this Actor pages through
  them 100 at a time.
- **LinkedIn ignores the work type, job type and experience level filters** on its public search.
  Glassdoor applies all three. The run warns you rather than pretending otherwise. `postedWithin`
  works on both.
- **LinkedIn pay and skills need `fetchDetails`**: they are read from the job description, which
  only the detail page has. US postings state pay about half the time (pay-transparency laws),
  Indian ones far less. Glassdoor supplies both either way.
- Fields a site does not expose come back `null`. Nothing is guessed: a LinkedIn salary is only
  taken from a line that states pay, never from bonuses, benefits or funding figures.

### Integrations

The output is an ordinary Apify dataset, so anything Apify supports works:

- **API** — `GET https://api.apify.com/v2/datasets/<datasetId>/items?format=json` (also `csv`,
  `xlsx`, `xml`, `rss`)
- **Make, Zapier, n8n** — through the Apify connectors
- **Scheduled runs** — a daily schedule plus `onlyNewJobs: true` gives you a feed of new postings
- **Webhooks** — fire on run completion to push results into your own system

#### Ready-made n8n workflow: new jobs in Google Sheets every morning

Import it and get a daily sheet of new LinkedIn and Glassdoor jobs, with no repeats: title,
company, location, salary, skills, rating and link. Built-in n8n nodes only, set up in about
3 minutes. Workflow and setup steps:
[n8n community post](https://community.n8n.io/t/get-new-linkedin-glassdoor-jobs-in-google-sheets-every-morning-no-login-no-duplicates/320897).

### FAQ

#### Do I need a LinkedIn or Glassdoor account or cookies?

No. Only public job listings are read. You are never asked for a login, credentials or cookies,
so no account of yours is at risk.

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

$0.40 for 1,000 jobs, or $1.20 with full descriptions (`fetchDetails`). There is no start fee
and no monthly rent. Set a max cost per run and the Actor stops the moment it is reached.

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

The Actor reads publicly available job postings only. It collects no personal data and no
candidate profiles. How you use the data is your responsibility, so check the rules that apply
to your use case.

#### How do I get only new jobs every day?

Create a daily schedule and set `onlyNewJobs: true`. The Actor remembers every job it has
returned to you and skips it next time, so you only pay for postings you have not seen.

#### Can I get salary data?

Yes. Glassdoor supplies a salary range for about 76% of listings, and `salary.source` says
whether the employer published it or Glassdoor estimated it. For LinkedIn, turn on `fetchDetails`:
pay is read from the description (about half of US postings, ~10% in India) and marked
`salary.source: "description"`.

#### Can I export to Excel, CSV or Google Sheets?

Yes. Every run's dataset downloads as JSON, CSV, Excel, XML or RSS, and the Make, Zapier and n8n
integrations push it to Google Sheets, Airtable or your CRM.

#### What if one site is temporarily unavailable?

The other still finishes, and the run reports which source could not be reached. You are not
charged for jobs you did not get.

#### Why is a field empty?

Because the site did not publish it for that listing. Nothing is inferred, so an empty field is
information too.

#### Can you add Indeed, Naukri or another job board?

Tell us on the Issues tab which board you need. Requests decide what gets added next.

# Actor input Schema

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

What to search for. Each keyword is searched in every location. Optional if you paste search URLs below instead.

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

Cities, states or countries, e.g. "Bangalore", "India", "New York". Glassdoor resolves each name to its own location filter and needs at least one location. Leave empty to search LinkedIn worldwide (Glassdoor is then skipped).

## `startUrls` (type: `array`):

Search URLs copied from LinkedIn or Glassdoor, e.g. https://www.linkedin.com/jobs/search?keywords=react%20developer\&location=India. Build the search on the site, then paste its URL here. Run in addition to the keywords above.

## `sources` (type: `array`):

Which job sites to search.

## `maxItemsPerSource` (type: `integer`):

Stop after this many jobs from each site. You only pay for jobs you get.

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

Only return jobs posted within this period. Works on both sites and is the one filter LinkedIn honours; narrower periods are faster and cheaper.

## `workType` (type: `array`):

Filter by remote / hybrid / on-site. Applied by Glassdoor. LinkedIn's public job search ignores this filter, so LinkedIn results are not narrowed by it.

## `jobType` (type: `array`):

Filter by employment type. Applied by Glassdoor. LinkedIn's public job search ignores this filter, so LinkedIn results are not narrowed by it.

## `experienceLevel` (type: `array`):

Filter by seniority. Applied by Glassdoor. LinkedIn's public job search ignores this filter, so LinkedIn results are not narrowed by it.

## `onlyEarlyApplicants` (type: `boolean`):

Only LinkedIn jobs marked "Be an early applicant", i.e. with few applicants so far, so you can apply before the crowd. LinkedIn applies this filter itself. Glassdoor publishes no applicant data and is not filtered by it.

## `minCompanyRating` (type: `string`):

Only jobs at employers rated at least this on Glassdoor. Applied by Glassdoor itself, so it costs nothing extra. LinkedIn has no company ratings and is not filtered by this.

## `companySize` (type: `string`):

Only jobs at companies of this size. Applied by Glassdoor; LinkedIn's public search has no size filter.

## `searchRadius` (type: `string`):

How far around a city to search. Only matters for city locations, not countries.

## `fetchDetails` (type: `boolean`):

Adds the full description, applicant count, seniority, industry, LinkedIn skills and salary (read from the description), plus company size, employee count, address, website and description. Priced as a detailed job. Tip: run with 512 MB or more.

## `includeDescriptionHtml` (type: `boolean`):

Also return the description as HTML (needs full job details).

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

Skip jobs returned by your previous runs. Ideal for scheduled runs: you only pay for new jobs.

## `dedupeAcrossSources` (type: `boolean`):

When the same job (title, company, city) is on several sites, return it once.

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

Apify Proxy is recommended. The default works for most searches.

## Actor input object example

```json
{
  "keywords": [
    "react developer"
  ],
  "locations": [
    "India"
  ],
  "startUrls": [],
  "sources": [
    "linkedin",
    "glassdoor"
  ],
  "maxItemsPerSource": 50,
  "postedWithin": "any",
  "workType": [],
  "jobType": [],
  "experienceLevel": [],
  "onlyEarlyApplicants": false,
  "minCompanyRating": "0",
  "companySize": "any",
  "searchRadius": "default",
  "fetchDetails": false,
  "includeDescriptionHtml": false,
  "onlyNewJobs": false,
  "dedupeAcrossSources": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `jobs` (type: `string`):

Every job found, in one unified schema.

## `jobDetails` (type: `string`):

Same jobs with description, skills, experience and applicant count.

## `runStats` (type: `string`):

Jobs per site, duplicates skipped and request counts.

# 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": [
        "react developer"
    ],
    "locations": [
        "India"
    ],
    "maxItemsPerSource": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("molded_mountainpass/linkedin-glassdoor-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": ["react developer"],
    "locations": ["India"],
    "maxItemsPerSource": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("molded_mountainpass/linkedin-glassdoor-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": [
    "react developer"
  ],
  "locations": [
    "India"
  ],
  "maxItemsPerSource": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call molded_mountainpass/linkedin-glassdoor-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,molded_mountainpass/linkedin-glassdoor-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/jZYn3CzbfLB9PTRuQ/builds/1MNQICGMw0GDnNMSY/openapi.json
