Jobs
Indeed Scraper: Scrape Indeed Jobs, Salaries and Company Data
Indeed API alternative: scrape jobs from 62 Indeed sites with numeric salaries, company size, revenue and CEO data, past the 1,000-result cap. With code.
Jobs
Indeed API alternative: scrape jobs from 62 Indeed sites with numeric salaries, company size, revenue and CEO data, past the 1,000-result cap. With code.
Indeed is the world’s largest job site, and for that reason it’s the default data source for salary research, hiring trend analysis and recruiting lead lists. Getting the data out is harder than it should be: the Indeed Publisher API is closed to new users, and every search on the site stops at about 1,000 results.
The Indeed Jobs Scraper handles both problems. It searches any of Indeed’s 62 country sites, applies Indeed’s own filters, continues past the 1,000-job cap by splitting the search into posting-date windows, and returns each job with full description, numeric salary and the employer’s company profile. No Indeed account, proxy setup or API key is needed.
Every row is one job, grouped roughly like this:
jobKey, title, normalizedTitle, jobUrl, applyUrl, isIndeedApply, descriptionText, jobType, experienceLevel, isRemote, isHybrid, attributes (skills, benefits, schedules), occupations.salary object with salaryText, salaryMin, salaryMax, salaryCurrency, salaryType (hourly, daily, weekly, monthly, yearly) and salarySource.companyName, companyUrl, companyWebsite, companyIndustry, companyEmployees, companyRevenue, companyCeo, companyHeadquarters, companyDescription, rating.location.city, state, postalCode, country, countryCode, latitude, longitude.postedAt, datePublished, age, postedToday, expired, isUrgentHire, isHighVolumeHiring.Two things set this apart from a basic Indeed scraper. Salaries come back as numbers from Indeed’s structured pay data, with salarySource telling you whether a figure came from the employer’s compensation field, Indeed’s estimate, or the description text. And company firmographics (headcount, revenue, website, CEO) come attached to every job, which is what turns job data into sales data.
query and location.maxResults at 50 for a first test.The country is detected from the location, or you can set country to a two-letter code (GB, DE, IN, AE, AU and so on).
{
"query": "title:(data analyst)",
"country": "GB",
"jobType": "fulltime",
"level": "mid_level",
"maxResults": 1000
}
title:(...) restricts matches to the job title. Indeed’s full search syntax works in query: "exact phrase", -exclude, title:("data engineer" or "data scientist") and company:Name.
{
"query": "registered nurse",
"location": "Texas",
"fromDays": 7,
"maxResults": 0
}
maxResults: 0 means “everything”. Above 1,000 results, the scraper keeps going in posting-date windows, newest first, until it has every matching job.
| Input | Values |
|---|---|
sort |
RELEVANCE, DATE |
fromDays |
Posted within N days, 0 for any |
radius |
Miles on US/UK sites, km elsewhere (default 25) |
jobType |
fulltime, parttime, contract, temporary, internship, perdiem |
remote |
remote, hybrid |
level |
no_experience, entry_level, mid_level, senior_level |
urls |
Specific Indeed job links or 16-character job keys |
includeDescriptionHtml |
Add formatted descriptionHtml |
searchCompanyInfo |
Look up company profiles for jobs Indeed doesn’t link |
Indeed applies these filters itself, so every saved row matches and you never pay for jobs that get thrown away.
Trimmed from a registered nurse search in Houston:
{
"jobKey": "804720bae170b72f",
"title": "Full - Time Home Infusion RN - Admissions RN",
"normalizedTitle": "registered nurse - admissions",
"jobUrl": "https://www.indeed.com/viewjob?jk=804720bae170b72f",
"companyName": "Option Care Enterprises, Inc.",
"companyWebsite": "https://navenhealth.com/",
"companyEmployees": "1,001 to 5,000",
"companyHeadquarters": "Sarasota, FL",
"rating": { "rating": 4.2, "count": 71 },
"location": { "city": "Houston", "state": "TX", "countryCode": "US", "latitude": 29.99817, "longitude": -95.269394 },
"jobType": ["Full-time"],
"experienceLevel": ["Entry level"],
"attributes": ["CPR Certification", "Nursing", "Care plan evaluation"],
"salary": {
"salaryText": "$40.78 - $67.97 an hour",
"salaryType": "hourly",
"salaryMin": 40.78,
"salaryMax": 67.97,
"salaryCurrency": "USD",
"salarySource": "COMPENSATION_FIELD"
},
"postedAt": "2026-10-01T18:44:42.057Z",
"postedToday": true,
"isUrgentHire": false
}
This script pulls software engineer jobs in Germany and computes a median salary from employer-provided figures only:
import os
from statistics import median
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("epicscrapers/indeed-scraper").call(run_input={
"query": "Softwareentwickler",
"country": "DE",
"jobType": "fulltime",
"maxResults": 2000,
})
mins = [
j["salary"]["salaryMin"]
for j in client.dataset(run["defaultDatasetId"]).iterate_items()
if j.get("salary")
and j["salary"]["salaryType"] == "yearly"
and j["salary"]["salarySource"] == "COMPENSATION_FIELD"
]
print(f"{len(mins)} salaries, median minimum EUR {median(mins):,.0f}")
Write queries in the local language for each site (German on de.indeed.com, Japanese on jp.indeed.com). Salaries come back in the local currency. From JavaScript, use client.actor("epicscrapers/indeed-scraper"). Over REST, the actor ID is epicscrapers~indeed-scraper.
Salary benchmarking. Run one role across cities or countries and compare salaryMin/salaryMax by salaryType. Filtering on salarySource lets you exclude Indeed’s estimates when you only want posted pay. Coverage varies by country and role. In US tests, a little over half of jobs carried a salary.
Lead generation for staffing agencies and B2B sales. Group by companyName, keep employers with several open roles, and you already have companyWebsite, companyEmployees, companyRevenue, companyIndustry and companyCeo for each one. isUrgentHire and isHighVolumeHiring flag the employers most likely to take an agency call.
Competitor hiring intelligence. company:Stripe (or any competitor) shows which roles they’re opening and where. Running it weekly turns this into a hiring timeline.
Daily job alerts. Save a task with sort: "DATE" and fromDays: 1, schedule it for each morning, and connect Slack or Google Sheets. Deduplicate across runs on jobKey.
Labor market dashboards. Count jobs by occupations, normalizedTitle or attributes over time, and map them with latitude/longitude. Because the schema is identical across all 62 sites, one dashboard can cover the US, UK, India and the Gulf.
Indeed’s coverage is broad, but local boards often have more listings in their home market. In India, Naukri has the deepest IT and GCC listings and Naukri-specific fields like CTC bands and AmbitionBox ratings. See the Naukri scraper guide. For Gulf roles with full package descriptions and consultant flags, see the NaukriGulf scraper guide. In Australia, SEEK dominates, and the SEEK scraper guide covers its classification filters.
Indeed’s Job Search (Publisher) API is closed to new users. The scraper uses the data Indeed’s mobile app shows and returns it as structured rows, so it serves as an Indeed API alternative.
Set maxResults above 1,000, or to 0. The scraper continues the search in posting-date windows. A nationwide nurse search returned 2,500 unique jobs in about 70 seconds.
The actor collects publicly visible job listings and employer information, and no job seeker data. You’re responsible for complying with Indeed’s terms and laws like GDPR. This isn’t legal advice.
No. It collects job listings and the employer profile shown with them, including the overall rating.
It uses pay-per-result pricing with no subscription. Check the Pricing tab on the actor page for current rates.
Enter a query and a location, and you’ll have Indeed jobs with salaries and company data in under a minute. Run the Indeed Jobs Scraper on Apify or see the actor page.