Use Indeed Job Search Scraper with Salary & Benefits Data with Python
Search Indeed by keyword and location, or supply direct Indeed search URLs, and get job titles, salaries, company ratings, benefits, remote-work status, and more. No login or API key needed.
1. Choose the data you need
Review the published README for supported collection modes, examples, and limits. The recipe below uses the current published input definition.
2. Prepare a source-based input
This JSON contains published prefills and required-field defaults. Review every value for your task before running it; it is not a promise of successful collection.
{
"country": "US",
"easyApplyOnly": false,
"expandBeyondCeiling": false,
"includeCompanyRatings": false,
"includeCompanyReviews": false,
"includeCompanySalaries": false,
"includeContacts": false,
"includeDescriptionHtml": false,
"location": "San Francisco",
"maxItems": 3,
"radius": 25,
"searchQueries": [
"web developer in San Francisco"
]
}
Download input.example.json and save your reviewed copy as input.json.
| Field | Type | Required | Description |
|---|---|---|---|
searchQueries | array | optional | Job searches. Write a location after " in " to search one city, e.g. `software engineer in New York`, `registered nurse in Houston, TX`. A query without " in " uses the Location field below, or searches the whole country. |
startUrls | array | optional | Indeed pages to scrape: filtered search URLs (filters in the URL are honored), company job pages like `https://www.indeed.com/cmp/Google/jobs`, or individual job links like `https://www.indeed.com/viewjob?jk=...`. Country sites such as `uk.indeed.com` work too. |
country | string | optional | Indeed country site to search. Results come in the site's language and salaries in its currency. |
location | string | optional | City, region or postal code for searches that don't name a location themselves, e.g. `Austin, TX`, `10001`, `London`. Leave empty to search the whole country. Ignored for remote-only searches (remote jobs are searched country-wide). |
radius | integer | optional | How far from the location to search. |
radiusUnit | string | optional | Unit for the search radius. |
sort | string | optional | How to order results: by relevance to the keywords, or with the newest postings first. |
datePosted | string | optional | Only jobs posted within this window. |
jobType | string | optional | Only jobs of this employment type. |
workplaceType | string | optional | Remote, hybrid or on-site jobs only. Remote searches run country-wide because Indeed's app index does not geo-attribute remote jobs. |
experienceLevel | string | optional | Only jobs asking for this experience level. |
educationLevel | string | optional | Only jobs asking for this education level. |
easyApplyOnly | boolean | optional | Only jobs that accept Indeed's one-click application. |
salaryMin | integer | optional | Only jobs paying at least this much per year (employer-stated salaries; hourly and monthly pay is compared at its annualized value). Jobs without a stated salary are kept. |
maxItems | integer | optional | Maximum number of job listings to save across all searches. |
maxItemsPerSearch | integer | optional | Optional cap per search query or URL. Defaults to the overall Maximum jobs value. |
includeDescriptionHtml | boolean | optional | Also save each job description as HTML next to the plain text. |
includeCompanyRatings | boolean | optional | Look up each employer's Indeed rating and review count. Off by default; a rating that cannot be read is left out of the record. |
includeContacts | boolean | optional | Extract email addresses and phone numbers written in the posting's own description text (pattern extraction, not an Indeed field). Off by default. |
includeCompanyReviews | boolean | optional | Fetch the first page of each employer's Indeed reviews (up to 20 full reviews with pros/cons and sub-ratings); combine with Include company ratings. Off by default. |
includeCompanySalaries | boolean | optional | Fetch each employer's Indeed salaries page (total salary reports, satisfaction and the broader salary-by-title list); combine with Include company ratings. Off by default. |
expandBeyondCeiling | boolean | optional | Indeed's app search stops at roughly 600-900 unique jobs per query. When a search reaches that ceiling, split its time range into date windows and merge them, so the run returns the full set Indeed's index holds for the query. Narrow searches are handled in a single pass. |
3. Start an Actor run
Set APIFY_TOKEN in your environment. Python 3.10 or newer is sufficient; this recipe uses no third-party packages.
Execution may incur charges. Review current pricing on Apify. The request asks for a 120-second timeout and a charge limit; these settings are subject to Apify’s pricing and do not guarantee an all-inclusive spending cap.
import json
import os
import urllib.request
# Save the schema-derived example as input.json; review and edit it first.
with open("input.json", encoding="utf-8") as stream:
actor_input = json.load(stream)
token = os.environ["APIFY_TOKEN"]
request = urllib.request.Request(
"https://api.apify.com/v2/acts/RXu7Xe475tOdKeSaK/runs?timeout=120&maxTotalChargeUsd=0.50",
data=json.dumps(actor_input).encode("utf-8"),
headers={"Authorization": "Bearer " + token, "Content-Type": "application/json"},
method="POST",
)
# This starts a potentially billable run. Do not automatically retry this POST.
with urllib.request.urlopen(request, timeout=40) as response:
run = json.load(response)["data"]
print("Run ID:", run["id"])
print("Status:", run["status"])
# Inspect and download results in Apify Console once the run succeeds.
4. Inspect the actual results
Open the run in Apify Console and wait for a successful completion. Use the published output schema to locate results and the dataset schema to understand declared views. Missing or optional record fields must not be treated as guaranteed values.
One record per Indeed job listing, with title, company, salary, benefits, remote-work status, full description and apply links.
Questions before you run
Which inputs are required?
No top-level fields are marked required in the published schema. Conditional requirements can still apply; check the README.
What does this guide verify?
The fields, prefills, and schema links are rendered from the published build. This is a usage recipe, not a paid live extraction test. Source availability and collection results can vary.
What if the run request times out?
Check Apify Console before retrying. The first request may already have created a run. Do not automatically repeat a run-creation POST.
Generated from source build sqbMLB30NaUVc43cb and its README and schemas. Source changes regenerate this guide; no third-party editorial claims are inferred.