# Jobs Scraper: Indeed, LinkedIn & Glassdoor Jobs API (`khadinakbar/jobs-scraper`) Actor

Search Indeed, LinkedIn and Glassdoor in one run. Title, company, location, salary, full description, apply URL. Only-new mode for schedules. Export JSON, CSV, Excel, API or MCP.

- **URL**: https://apify.com/khadinakbar/jobs-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Automation, Lead generation, MCP servers
- **Features:** Limited permissions
- **Stats:** 469 total users, 15 monthly users, 98.5% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 job results

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?

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

## Jobs Scraper: Indeed, LinkedIn & Glassdoor Jobs API

Search **Indeed, LinkedIn and Glassdoor in one run** and get one clean list of jobs: title, company, location, salary, full description, apply link, posting date and the board it came from. Duplicates across boards are removed, and a scheduled run can return **only the jobs that are new since last time**. No login, no cookies, no browser: results come back in minutes, not hours.

### What you get

| Data | Indeed | LinkedIn | Glassdoor |
|---|---|---|---|
| Title, company, location, apply link | yes | yes | yes |
| Posted date | yes | yes | approximate (days) |
| Salary | when listed | when listed | when listed |
| Full description | yes | yes | short snippet only |
| Applicants, seniority, company size, industry | - | yes | company rating |
| Remote flag, job type | yes | yes | remote flag |

Every row has `description_status` (`full`, `snippet` or `unavailable`), so you always know what you got. Missing data is empty, never filled with made-up text.

### Cost

You pay per job returned (see the live **Pricing** tab for the exact price on your plan). Roughly **$3 to $4 per 1,000 jobs**. Turning off "Get full job descriptions" makes runs faster and lighter without changing the per-job price. Only-new mode never charges for jobs you already received.

### Quick start

```json
{
  "searchQuery": "data analyst",
  "location": "Austin, TX",
  "platforms": ["indeed", "linkedin", "glassdoor"],
  "maxResults": 100,
  "hoursOld": 168
}
```

Several searches in one run:

```json
{
  "queries": ["data analyst", "business analyst"],
  "locations": ["Austin, TX", "Remote"],
  "maxResults": 300,
  "excludeCompanies": ["staffing"]
}
```

Run every morning and get only new postings:

```json
{ "searchQuery": "python developer", "location": "United States", "hoursOld": 24, "onlyNew": true }
```

### Input

| Field | Purpose |
|---|---|
| `searchQuery`, `queries` | One job title or many (up to 20 title/place pairs per run) |
| `location`, `locations` | City, state or country; many allowed |
| `platforms` | `indeed`, `linkedin`, `glassdoor` (default all three) |
| `maxResults` | 1 to 1000 jobs in total (free Apify plans: 25 per run) |
| `includeDescriptions` | Full description lookup on LinkedIn and Indeed (default on) |
| `jobType`, `isRemote`, `hoursOld` | Employment type, remote only, posted within X hours |
| `experienceLevel` | LinkedIn seniority filter |
| `radius`, `country` | Indeed search radius; country site for Indeed and Glassdoor |
| `includeCompanies`, `excludeCompanies` | Keep or drop companies by name |
| `deduplicate` | One row per job across boards (title + company + city) |
| `onlyNew`, `trackChanges` | Skip jobs seen in an earlier run of the same search; mark new / updated / unchanged |

### Output (one row per job)

`job_id`, `job_title`, `company_name`, `location`, `is_remote`, `salary_min`, `salary_max`, `salary_currency`, `salary_period`, `salary_range`, `salary_source` (employer or board estimate), `job_type`, `seniority_level`, `description`, `description_status`, `skills`, `posted_date`, `apply_url`, `easy_apply`, `applicants`, `company_rating`, `company_reviews_count`, `company_size`, `company_industry`, `company_website`, `company_url`, `is_sponsored`, `platform`, `search_query`, `search_location`, `source_url`, `scraped_at`, and `change_status` when tracking is on.

The run also saves an `OUTPUT` record with `outcome` (`COMPLETE`, `PARTIAL`, `VALID_EMPTY`, `INVALID_INPUT` or `UPSTREAM_FAILED`), per-board search counts, how many descriptions are full, and a plain-language `agentSummary` for AI agents.

### Honest limits

- **Indeed** returns about 45 jobs per search view. To reach more, the Actor runs several views of the same search (newest first, most relevant, last day / 3 days / week / two weeks, job types, wider radius) and removes duplicates. A very narrow search can therefore return fewer jobs than you asked for; the run says so.
- **Glassdoor** returns about 30 jobs per search and a short snippet instead of the full description. City searches work for about 40 major US cities and country-wide searches work everywhere; other places are skipped on Glassdoor and the run reports it.
- **Company filters** (`includeCompanies`) are applied to the first 5 LinkedIn result pages and to Indeed's result views, so rarely-hiring companies can be missed; use specific job titles for better matches.
- If one board is blocked or runs out, the others fill the requested number. If every board fails, the run ends as failed with no charge.
- Public listings only. You are responsible for using the data in line with the job boards' terms and local law (including privacy rules for any personal data in a listing).

### Use it from AI agents and tools

Works through the Apify API, SDKs, schedules, webhooks and the Apify MCP server. Example agent prompt: *"Find 50 new remote data analyst jobs posted in the last 24 hours on Indeed and LinkedIn and summarise the top companies."*

### FAQ

**Why is a description empty?** The board did not show one for that listing. Check `description_status`.
**Why fewer jobs than `maxResults`?** The boards ran out of matching jobs for your filters (the run message tells you). Try a wider location or more job titles.
**Can I run it daily?** Yes. Use `onlyNew` with a schedule; the state is kept per search.
**Need one board only?** See [Indeed Jobs Scraper](https://apify.com/khadinakbar/indeed-job-scraper), [Glassdoor Jobs Scraper](https://apify.com/khadinakbar/glassdoor-jobs-scraper) or [LinkedIn Jobs Scraper](https://apify.com/khadinakbar/linkedin-jobs-scraper).
**Other job sources?** [Google Jobs Scraper](https://apify.com/khadinakbar/google-jobs-scraper), [ZipRecruiter Jobs Scraper](https://apify.com/khadinakbar/ziprecruiter-jobs-scraper), [Foundit Jobs Scraper](https://apify.com/khadinakbar/foundit-jobs-scraper) (India), [LinkedIn Company Jobs Scraper](https://apify.com/khadinakbar/linkedin-company-jobs-scraper).

### What's new

- **Version 2:** rebuilt without a browser: much faster and cheaper to run; honest descriptions (`description_status`); several titles and locations per run; only-new and change tracking; company and experience filters; Indeed radius; cross-board duplicates matched on title + company + city; free plans limited to 25 jobs per run.

# Actor input Schema

## `searchQuery` (type: `string`):

Job title, skill or keyword to search, for example 'data analyst' or 'remote python developer'. Use this for one search; use 'Several job titles' below for many.

## `queries` (type: `array`):

Extra job titles or keywords. Each one is searched in every location and the results are merged without duplicates. Up to 20 title and place pairs per run.

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

City, state or country, for example 'Austin, TX', 'London' or 'United States'. Glassdoor supports country-wide searches and about 40 major US cities; other places are searched on Indeed and LinkedIn only (the run reports this).

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

Extra locations. Each one is searched for every job title.

## `platforms` (type: `array`):

Which boards to search. Leave all three for the widest coverage. If one board is blocked or runs out of jobs, the others fill the requested number.

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

Maximum number of jobs to return across all boards (1 to 1000). You pay per job returned. Free Apify plans are limited to 25 per run.

## `includeDescriptions` (type: `boolean`):

On: LinkedIn and Indeed return the full description (one extra lookup per job). Off: faster and lighter, only the search-result fields. Glassdoor always returns a short snippet. Each row says which one it has in description_status.

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

Filter by employment type. 'All' means no filter.

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

Only return remote jobs.

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

Only jobs posted in the last X hours (24 = last day, 168 = last week). 0 means no filter.

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

Filter LinkedIn jobs by seniority. Indeed and Glassdoor ignore this filter.

## `radius` (type: `integer`):

Distance around the location for Indeed. Leave empty for the default.

## `country` (type: `string`):

Two-letter country for the Indeed and Glassdoor sites, for example US, GB, CA, AU, DE, FR, IN.

## `includeCompanies` (type: `array`):

Keep only jobs whose company name contains one of these words.

## `excludeCompanies` (type: `array`):

Drop jobs whose company name contains one of these words, for example staffing agencies.

## `deduplicate` (type: `boolean`):

Same job title at the same company in the same city on two boards is delivered once.

## `onlyNew` (type: `boolean`):

For scheduled runs: skip jobs already delivered by an earlier run of the same search. Skipped jobs are not charged.

## `trackChanges` (type: `boolean`):

Adds change_status to every row, compared with the previous run of the same search. Switched on automatically by 'Only new jobs'.

## Actor input object example

```json
{
  "searchQuery": "software engineer",
  "location": "United States",
  "platforms": [
    "indeed",
    "linkedin",
    "glassdoor"
  ],
  "maxResults": 5,
  "includeDescriptions": true,
  "jobType": "all",
  "isRemote": false,
  "hoursOld": 0,
  "country": "US",
  "deduplicate": true,
  "onlyNew": false,
  "trackChanges": false
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset of job listings. Each item includes job_title, company_name, location, is_remote, salary_min, salary_max, salary_currency, job_type, description, skills, posted_date, apply_url, platform, and more.

# 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 = {
    "searchQuery": "software engineer",
    "location": "United States",
    "platforms": [
        "indeed",
        "linkedin",
        "glassdoor"
    ],
    "maxResults": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/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 = {
    "searchQuery": "software engineer",
    "location": "United States",
    "platforms": [
        "indeed",
        "linkedin",
        "glassdoor",
    ],
    "maxResults": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/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 '{
  "searchQuery": "software engineer",
  "location": "United States",
  "platforms": [
    "indeed",
    "linkedin",
    "glassdoor"
  ],
  "maxResults": 5
}' |
apify call khadinakbar/jobs-scraper --silent --output-dataset

```

## MCP server setup

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