# Indeed Jobs Scraper - Salaries, Ratings & Apply Links (`scrapewise/indeed-jobs-scraper`) Actor

Scrape Indeed jobs in 60+ countries by keyword, location, radius, remote, job type and date: title, company, rating, salary range, job type, skills, posted date, full description and the direct apply link. No login. onlyNew for daily alerts. Error rows are free.

- **URL**: https://apify.com/scrapewise/indeed-jobs-scraper.md
- **Developed by:** [Scrapewise Data](https://apify.com/scrapewise) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.85 / 1,000 job delivereds

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

## Indeed Jobs Scraper: jobs from 60+ countries with salaries, company ratings and apply links

Indeed Jobs Scraper collects **job listings from Indeed in more than 60 countries**, without an Indeed account,
cookies or a browser. Give it job titles or keywords (or paste Indeed search links) and each job comes back as one
clean row: title, company, company rating and review count, location, remote or hybrid flag, job type, salary range
with period and currency, the skills and benefits Indeed tags on the job, posted date, the full description and the
direct apply link on the employer's own career site.

It is used for job boards and job alert bots, salary benchmarking, labour market research, recruiting and sales
prospecting (which companies are hiring for what, and where), and to feed AI agents and RAG pipelines with fresh
openings.

### At a glance

| What | Price |
|---|---|
| Job delivered | **US$ 1.00 per 1,000 jobs** (US$ 0.001 each) |
| Run start | US$ 0.005 per run |

- 5 keywords x 100 jobs = 500 jobs = **US$ 0.505**. A daily alert of 50 new jobs costs about US$ 1.70 a month.
- Error rows, duplicates and jobs skipped by `onlyNew` are never charged. `maxItems` is a hard cap, and a spending
  limit set on the run stops it cleanly with everything delivered so far.
- Fast: about 100 jobs per second of network time, so even 1,000 jobs finish in well under a minute.

### Quick start

```json
{
  "queries": ["data analyst"],
  "country": "US",
  "remote": "remote",
  "maxItems": 50
}
```

More examples:

```json
{
  "queries": ["registered nurse", "nurse practitioner"],
  "country": "US",
  "location": "Chicago, IL",
  "radius": 25,
  "jobType": ["full-time"],
  "datePosted": 7,
  "maxItems": 200
}
```

```json
{
  "startUrls": [
    "https://uk.indeed.com/jobs?q=warehouse+operative&l=London&fromage=3",
    "https://www.indeed.com/viewjob?jk=eb026cacfa74a43b"
  ],
  "maxItems": 100
}
```

### Input

| Field | What it does |
|---|---|
| `queries` | Job titles or keywords, one per line. Each one is a separate search. |
| `country` | Indeed country site: US, GB, CA, AU, IN, DE, FR, NL, IE, NZ, SG, AE, ZA, ES, IT, BR, MX and 45 more. Default US. |
| `location` | City, state, region or postal code inside that country, for example `Austin, TX` or `Manchester`. Empty = whole country. |
| `radius` | Miles around the location (0, 5, 10, 15, 25, 35, 50 or 100). Default 25. |
| `remote` | `any` (default), `remote` (remote only, hybrid excluded) or `hybrid`. |
| `jobType` | Any of `full-time`, `part-time`, `contract`, `internship`, `temporary`, `per-diem`, `volunteer`. |
| `datePosted` | Only jobs that appeared on Indeed in the last N days (1, 3, 7, 14...). |
| `sortBy` | `relevance` (default) or `date`. `onlyNew` always uses `date`. |
| `startUrls` | Indeed search links (keyword, location, radius, `fromage`, `jt` and the remote filter are read from the link; the country comes from the domain, such as `uk.indeed.com` or `indeed.de`) or job links with `jk=`. |
| `includeDescription` | Full description as text and HTML (default on). Off = lighter rows. |
| `maxItems` | Cap for the whole run. Default 50, 0 = no cap. |
| `onlyNew` | Remembers the jobs already delivered for the same search in your account and delivers only new ones. |
| `proxyConfiguration` | Apify datacenter proxy by default; the run moves to residential by itself if Indeed refuses it. |

Inputs written for other Indeed tools also work: `position`, `keyword`, `searchQueries`, `maxResults`, `remoteOnly`,
`fromDays` and `startUrls` with plain strings or `{ "url": ... }` objects.

### Output

One row per job. Fields that Indeed does not publish for a job are `null` (salary, rating and logo depend on the
employer; the fill rates below are from 360 jobs across the US, the UK and India on 17 Oct 2026).

| Field | Description | Filled |
|---|---|---|
| `jobKey` | Indeed job key (stable ID, used by `onlyNew`) | 100% |
| `title` | Job title | 100% |
| `companyName` | Employer name | 100% |
| `companyRating`, `companyReviewCount` | Indeed company rating (1 to 5) and number of reviews | 65 to 75% |
| `companyEmployees`, `companyRevenue`, `companyIndustry`, `companyWebsite`, `companyLogo`, `companyDescription` | Company profile from Indeed, when the company has one | 12 to 55% |
| `companyIndeedUrl` | Company page on Indeed | ~94% |
| `location`, `city`, `state`, `postalCode`, `country` | Where the job is (as Indeed formats it) | 100% (location, country) |
| `isRemote`, `isHybrid` | Remote and hybrid flags from Indeed's own job attributes | 100% |
| `jobTypes` | `full-time`, `part-time`, `contract`, `internship`, `temporary`... | ~83% |
| `salaryMin`, `salaryMax`, `salaryPeriod`, `salaryCurrency` | Salary range, period (`hour`, `day`, `week`, `month`, `year`) and currency | ~54% (higher in the US and UK) |
| `attributes` | Skills, benefits, schedule and other tags Indeed puts on the job | ~100% |
| `postedAt`, `firstSeenOnIndeedAt` | Publication date and the moment Indeed indexed the job (ISO 8601, UTC) | 100% |
| `applyUrl` | Apply link, usually the employer's career site or ATS | 100% |
| `url` | Job page on Indeed | 100% |
| `description`, `descriptionHtml` | Full job description as clean text and as HTML | 100% |
| `searchCountry`, `sourceQuery`, `scrapedAt` | Which search produced the row and when | 100% |
| `errorCode`, `error` | Filled only on error rows (free) | |

Real row (description shortened):

```json
{
  "type": "job",
  "jobKey": "eb026cacfa74a43b",
  "title": "Manager, Data Analyst (Remote)",
  "companyName": "Fanatics",
  "companyRating": 3.5,
  "companyReviewCount": 1266,
  "companyEmployees": "10,000+",
  "companyRevenue": "$1B to $5B (USD)",
  "companyWebsite": "http://www.fanaticsinc.com",
  "companyIndeedUrl": "https://www.indeed.com/cmp/Fanatics-fb44f34a",
  "location": "Atlanta, GA",
  "city": "Atlanta",
  "state": "GA",
  "country": "US",
  "isRemote": true,
  "isHybrid": false,
  "jobTypes": ["full-time"],
  "salaryMin": 138000.0,
  "salaryMax": 170000.0,
  "salaryPeriod": "year",
  "salaryCurrency": "USD",
  "attributes": ["Performance dashboard reports", "Dashboard development", "Operational analysis", "Data modeling"],
  "postedAt": "2026-09-30T05:00:00Z",
  "firstSeenOnIndeedAt": "2026-09-30T18:42:34Z",
  "applyUrl": "https://grnh.se/2i91wjpb9us",
  "url": "https://www.indeed.com/viewjob?jk=eb026cacfa74a43b",
  "description": "About Us\n\nFanatics is building a leading global digital sports platform. ...",
  "searchCountry": "US",
  "sourceQuery": "data analyst",
  "scrapedAt": "2026-10-17T22:54:51Z"
}
```

In the Apify Console the **Jobs** view shows company, title, location, remote, job type, salary, rating, posted date
and both links as a table; the full rows export to JSON, CSV or Excel.

### Daily job alerts with onlyNew

Turn on `onlyNew` and schedule the same input every day. The Actor keeps the keys of the jobs it delivered for each
search in a named key-value store of your own account, sorts by date and delivers only jobs it has never sent you.
Jobs skipped this way cost nothing, and a search with nothing new stops after a few pages. Changing the keyword,
country, location or filters starts a new memory for that search.

### Errors you may see

Error rows are always free and come with `errorCode` and a plain-English `error`:

| errorCode | Meaning |
|---|---|
| `INVALID_INPUT` | A field has a value Indeed does not know (country code, job type, number). Nothing was searched. |
| `INVALID_URL` | A link in `startUrls` is not an Indeed search or job link. |
| `NO_RESULTS` | Indeed has no job for that search and filters. Try a broader keyword, a bigger radius or fewer filters. |
| `NOT_FOUND` | A job link points to a job that is no longer on Indeed. |
| `INVALID_SEARCH` | Indeed rejected the search itself (very unusual characters). |
| `BLOCKED` | Indeed refused every attempt for that search. Run it again a few minutes later. |

### Integrations, scheduling and AI agents

- **Schedule** a daily or hourly run with `onlyNew` in [Apify schedules](https://docs.apify.com/platform/schedules)
  to get only fresh jobs.
- **Export** as JSON, CSV, Excel or XML, or read the dataset from the [Apify API](https://docs.apify.com/api/v2).
- **Connect** it to Make, n8n, Zapier, Slack, Airtable or Google Sheets through
  [Apify integrations](https://docs.apify.com/platform/integrations) to post new jobs to a channel or a sheet.
- **AI agents:** call it as a tool through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp)
  in Claude, ChatGPT, Cursor or any MCP client, for example "find remote data analyst jobs posted in the last 3 days
  in the US with a salary above 90k and list the companies and apply links".

### FAQ

**Do I need an Indeed account or cookies?** No. The Actor reads the same public job search that the Indeed mobile app
shows to a visitor who is not signed in.

**Which countries work?** Every Indeed country site in the `country` list (62 of them). Each country has its own
index, language and currency, so search in the language people use there (for example `Datenanalyst` in Germany).

**How many jobs can one search return?** Indeed shows up to about 1,000 jobs per search. For more, split the search
by location (several cities), by `datePosted`, or by job type, and run them together in one input.

**Why is the salary empty on some jobs?** Many employers do not publish one, and the Actor returns only the salary
the employer published, never a guess. Salary coverage is highest in the US and the UK.

**Is the apply link the employer's site?** Usually yes: Indeed gives the employer's career site or ATS link (Workday,
Greenhouse, Lever, SuccessFactors and others). Jobs that only accept Indeed Apply link to the Indeed job page.

**Does it collect personal data?** No. It returns job ads and company information only. Email addresses and phone
numbers written inside descriptions are replaced with `[contact removed]`.

**Why US$ 1.00 per 1,000 jobs?** It covers a full row per job (description, salary, rating, skills, apply link) on a
fast, light source, and stays well below the per-job prices common for Indeed data, with no monthly fee.

### Limitations

- Up to about 1,000 jobs per search, as on Indeed itself.
- Salary, company rating and company profile exist only when Indeed has them (see the fill rates above).
- `radius` is in miles, as Indeed's own filter.
- Results reflect what Indeed shows at run time; jobs closed after the run stay in your dataset.

### Changelog

- **17 Oct 2026**: first version. Keyword and link search in 62 Indeed countries, location and radius, remote,
  hybrid, job type and date filters, company rating and profile, salary with period and currency, skills and benefit
  tags, full description, direct apply link, `onlyNew` for alerts, free error rows.

# Actor input Schema

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

Job titles or keywords, one per line, for example data analyst or registered nurse. Each keyword is one search in the country below. Leave empty when you paste Indeed links further down.

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

Which Indeed country site to search. Each country has its own job index and currency.

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

City, state, region or postal code inside the country, as you would type it on Indeed, for example Austin, TX or London. Empty = the whole country.

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

Search radius around the location, in miles (Indeed uses 0, 5, 10, 15, 25, 35, 50 or 100). Ignored without a location.

## `remote` (type: `string`):

Keep only remote jobs, only hybrid jobs, or everything.

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

Keep only these job types (several = any of them). Empty = all.

## `datePosted` (type: `integer`):

Only jobs that appeared on Indeed in the last N days, for example 1, 3, 7 or 14. Empty = any date.

## `sortBy` (type: `string`):

Order of the results. onlyNew always uses Most recent.

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

Optional: Indeed search links copied from the address bar (keyword, location, radius, date, job type and remote filters are read from the link; the country comes from the domain) or job links with jk=<job key>.

## `includeDescription` (type: `boolean`):

On: each row has the full description as text and HTML. Off: smaller and faster rows with every other field.

## `maxItems` (type: `integer`):

Hard cap for the whole run, across all searches. 0 = no cap (Indeed shows up to about 1,000 jobs per search).

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

On: remembers the jobs delivered in earlier runs of the same search (in your account) and delivers only jobs not seen before. Skipped jobs are free.

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

Apify datacenter proxy by default. If Indeed refuses it, the run switches to residential by itself. Change it only if you know you need to.

## Actor input object example

```json
{
  "queries": [
    "data analyst"
  ],
  "country": "US",
  "radius": 25,
  "remote": "remote",
  "sortBy": "relevance",
  "includeDescription": true,
  "maxItems": 50,
  "onlyNew": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `resultsCsv` (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 = {
    "queries": [
        "data analyst"
    ],
    "country": "US",
    "remote": "remote",
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapewise/indeed-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 = {
    "queries": ["data analyst"],
    "country": "US",
    "remote": "remote",
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapewise/indeed-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 '{
  "queries": [
    "data analyst"
  ],
  "country": "US",
  "remote": "remote",
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scrapewise/indeed-jobs-scraper --silent --output-dataset

```

## MCP server setup

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