# Indeed Jobs Scraper: Search, Company Pages, 60+ Countries (`leadproof/indeed-jobs`) Actor

Scrape Indeed job listings with full descriptions and salaries, no login. Search by keyword and location in 60+ countries, pull every open role from a company page, or check job keys. One flat row per job. Pay per job.

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

## Pricing

from $0.30 / 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

## Indeed Jobs Scraper

Pull Indeed job listings with the **full description, salary, employer details and posting date** into a clean table, with **no login, no cookies and no API key**. Search any of 60+ Indeed country sites by keyword and location, list every open role on a company page, or look up job keys you already have. **$0.50 per 1,000 jobs, plus $0.005 per run.**

### What you get

One row per job:

| Column | Example |
|---|---|
| `title`, `company`, `formatted_location`, `country` | Registered Nurse, Ascension, Austin, TX 78723, US |
| `remote_type`, `job_types` | remote, \["fulltime"] |
| `salary_min`, `salary_max`, `salary_period`, `salary_currency`, `salary_is_estimate` | 78561, 110905, year, USD, false |
| `posted_at`, `date_on_indeed` | 2026-09-14T00:00:00Z |
| `description_text` (and `description_html` on request) | the whole posting, not a snippet |
| `benefits`, `schedule`, `pay_types`, `requirements_and_skills` | \["Health insurance", "401(k) matching"], \["Night shift", "Full-time"], \["Hourly pay"], \["RN License", "BLS Certification"] |
| `occupations`, `normalized_title` | \["Nursing Occupations", "Patient Care Nursing Occupations"], registered nurse - operating room |
| `is_urgent_hire`, `is_high_volume_hiring`, `is_repost`, `expired`, `expiration_date` | hiring signals straight from Indeed |
| `company_website`, `company_industry`, `company_size`, `company_revenue`, `company_ceo`, `company_logo` | employer profile fields when Indeed has them |
| `street_address`, `latitude`, `longitude` | precise location when the posting gives one |
| `url`, `apply_url`, `external_apply_url`, `job_key`, `company_key` | Indeed links, the employer's own apply page when the job is applied to off Indeed (most postings), and the stable Indeed keys |

Full field list in the Output tab.

### How to use it

1. **Keywords and locations.** Add job titles, skills or company names and the cities or regions you care about. Every keyword is searched in every location; results are merged and deduplicated by job key. Leave locations empty to search the whole country.
2. **Country.** Pick the Indeed site (`us`, `uk`, `ca`, `de`, `il`, `in` ...). The scraper routes through proxies in that country.
3. **Filters.** Posted within 1 to 30 days, remote only, job types, sort by date for daily runs.
4. **Limits.** `maxJobsPerSearch` caps each keyword x location, `maxJobs` caps the whole run. Set a maximum total charge on the run to cap spending as well.
5. Run it. Download the dataset as JSON, CSV or Excel, or read it through the API.

#### Company mode

Put company page slugs or URLs in **Company pages** (`https://www.indeed.com/cmp/Ascension`) to get every role on that employer's jobs tab. Works together with keyword search in the same run.

#### Job key lookup

Put job keys (the `jk=` value in any Indeed job URL) in **Job keys** to fetch their descriptions. Keys Indeed no longer serves are listed under `job_keys.missing` in the run summary.

### Input example

```json
{
  "keywords": ["registered nurse", "nurse practitioner"],
  "locations": ["Austin, TX", "Dallas, TX"],
  "country": "us",
  "postedWithinDays": "7",
  "sort": "date",
  "maxJobsPerSearch": 200,
  "maxJobs": 1000
}
```

### Run summary

The `SUMMARY` record in the key-value store lists, per search and per company, how many jobs were found and written and why the search stopped (`end_of_results`, `max_per_search`, `max_jobs`, `charge_limit`, `blocked`), plus request, retry and transfer counts.

### Pricing

Pay per event: **$0.0005 per job** written to the dataset and **$0.005 per run start**. Deduplicated rows are never charged twice. A run that finds nothing costs only the start fee. Discounted job prices apply on higher Apify plans.

### Good to know

- Indeed applies either a date window or its job type and remote filters, never both. When you set **Posted within**, the type and remote filters are applied to the results after the search, so a small first page can come back with fewer rows than expected.
- Indeed returns a few hundred results per search at most. Split broad searches by city or by role variant to go wider.
- Salary ranges marked `salary_is_estimate: true` are Indeed's estimates, not the employer's numbers.
- The scraper reads public listings only. It does not log in, does not apply, and honours your limits.

### Related

- [Career Page Jobs Scraper](https://apify.com/leadproof/huntboard-career-jobs) - jobs straight from company career sites on Greenhouse, Lever, Ashby, Workday and 9 more ATS.
- [Google Maps Verified Leads](https://apify.com/leadproof/google-maps-verified-leads) - local business leads with verified emails.
- More at [leadproof.co](https://leadproof.co).

# Actor input Schema

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

Job titles, skills or company names to search for. Each keyword is searched separately for every location and the results are merged and deduplicated by job key. Indeed's advanced syntax works, for example title:("software engineer") -intern.

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

City, state, postal code or region, as you would type it on Indeed. Leave empty to search the whole country.

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

Which Indeed country site to search. Two-letter code: us, uk, ca, au, de, fr, il, in, and 60 more.

## `postedWithinDays` (type: `string`):

Only jobs Indeed listed in the last N days. Indeed cannot combine this with its job type and remote filters, so when it is set those two are applied to the results after the search.

## `remote` (type: `boolean`):

Keep only jobs Indeed tags as remote.

## `jobTypes` (type: `array`):

Keep only these job types.

## `radiusMiles` (type: `integer`):

Search radius around each location.

## `sort` (type: `string`):

Relevance is Indeed's default order. Date returns the newest postings first, which is the right choice for daily runs.

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

Stop each keyword x location search after this many jobs. Indeed serves a few hundred results per search at most; use several keywords or locations to go wider.

## `maxJobs` (type: `integer`):

Hard cap on rows written and charged in this run, across all modes.

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

Company mode: Indeed company slugs or full company page URLs (https://www.indeed.com/cmp/Ascension). Returns every open role listed on the company's jobs tab. Can be combined with keyword search.

## `jobKeys` (type: `array`):

Lookup mode: Indeed job keys (the jk= value in a job URL). Returns the description for each key that is still live; keys Indeed no longer serves are reported in SUMMARY as missing.

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

Add the description\_html column next to the plain text one.

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

Indeed's search API answers from Apify datacenter proxies (the cheap default); its HTML pages (company pages, job key lookups) refuse them, so the scraper switches to residential proxies in the search country by itself when a request is refused. Pick RESIDENTIAL here to use residential for everything, or bring your own proxies.

## Actor input object example

```json
{
  "keywords": [
    "registered nurse"
  ],
  "locations": [
    "Austin, TX"
  ],
  "country": "us",
  "postedWithinDays": "",
  "remote": false,
  "jobTypes": [],
  "radiusMiles": 50,
  "sort": "relevance",
  "maxJobsPerSearch": 100,
  "maxJobs": 500,
  "companies": [],
  "jobKeys": [],
  "includeDescriptionHtml": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One item per job: title, company, location, remote type, job types, salary, dates, full description, attributes, URLs.

## `jobsCsv` (type: `string`):

The same rows as a CSV download.

## `summary` (type: `string`):

Per search: jobs found, pages requested, stop reason; per company: jobs found; job keys missing; totals, charge counts and proxy stats.

# 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": [
        "registered nurse"
    ],
    "locations": [
        "Austin, TX"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("leadproof/indeed-jobs").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": ["registered nurse"],
    "locations": ["Austin, TX"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("leadproof/indeed-jobs").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": [
    "registered nurse"
  ],
  "locations": [
    "Austin, TX"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call leadproof/indeed-jobs --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,leadproof/indeed-jobs"
        }
    }
}
```

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/V7UBUClyOOp54nijc/builds/AhRSQfNLKefHahBlQ/openapi.json
