Indeed Jobs Scraper — Salaries, Benefits & Company Data
Pricing
from $3.00 / 1,000 jobs
Indeed Jobs Scraper — Salaries, Benefits & Company Data
Indeed jobs scraper and API: every posting with its full description, the employer's salary and Indeed's estimate in USD, benefits and schedule, company industry, size, revenue, CEO and website. 74 countries, pasted Indeed URLs, filters that never bill, a new-jobs monitor. $3 per 1,000 jobs.
Pricing
from $3.00 / 1,000 jobs
Rating
0.0
(0)
Developer
Spool
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Indeed jobs scraper and API: every posting with its full description, the employer's pay annualised in USD, benefits, schedule and skills as Indeed tags them, and the company's industry, size, revenue, CEO and website, from any of Indeed's 74 country sites. Rows are deduplicated, located and classified (department, seniority, job category, employment type, years of experience, visa sponsorship, education, 190 technologies), filtered before anything is charged, and delivered page by page while the next page is still loading.
Data Engineer FanDuel $116,000–$145,000 /yr hybrid Commuter assistance · 401(k) via FanDuelCorporate Accountant Lancashire County Council £42,123–£47,665 /yr onsite Company pension · Employee discount via the council's siteContact Center Representative Aloha Pacific FCU $18.00–$23.98 /hr remote Health insurance · Paid holidays via Aloha Pacific FCU
What a run costs. $0.003 per job row, so 1,000 jobs are $3, the same on every plan. The default run below asks for 200 jobs and costs about $0.60. Duplicates, rows a filter removed and empty pages cost nothing.
Try it in one minute
- Press Try for free and keep the prefilled input, or paste this:
{ "searchTerms": ["data analyst"], "location": "Chicago, IL" }
- Press Start. Indeed is read 100 postings at a time through its own JSON API, each page is enriched and delivered as it lands.
- Open the Output tab: the Jobs, Salaries, Benefits and schedule, Companies and Technologies views each show their own columns. Export as JSON, CSV or Excel, or read the dataset from the API.
Measured on the platform, 31 October 2026, build 1.0, four runs started in the same minute: the default search
(software engineer, whole United States, 200 rows) delivered 200 jobs in 4.8 seconds, first rows at 2.2 seconds,
every row with a description, 97 with the employer's pay; data engineer in New York, 200 rows in 32 seconds, 187
with pay; customer service representative, remote, employer pay required: 200 rows in 59 seconds, 400 postings
read, the 159 without pay removed before billing; accountant in Manchester on uk.indeed.com, 100 rows in 7 seconds.
Why this one
| This Actor | A typical Indeed scraper | |
|---|---|---|
| Source | Indeed's own JSON API, the one its mobile app uses, 100 postings per request with the full description | HTML pages, 15 per page, the description fetched one by one |
| Pay | the employer's stated pay as min, max, interval and currency, annualised and in USD; ranges written only in the text read out too; the recruiter's own pay text kept | one salary string, or none |
| Benefits, schedule, skills, workplace type | every attribute Indeed shows, sorted into benefits, schedule, skills and pay types | not delivered |
| Company | industry, size, revenue, CEO, website, logo, header image, address, description, Indeed company page | name and maybe a logo |
| Where the posting came from | postedVia: the employer's site, an ATS or a board | not delivered |
| Classification | department, seniority, job category, employment type, years of experience, visa sponsorship, education, 190 technologies | none |
| Filters | 14 filters applied before billing; removed rows cost nothing | board-side filters only |
| Countries | 74 Indeed sites, by name or from a pasted URL | often US only |
| Pasted Indeed URLs | yes, any country site; keywords, place, radius, date, remote, job type and level read from the URL | sometimes |
| Only what is new | monitor mode remembers what a search already delivered | no |
| Delivery | page by page, first rows in seconds | all at the end |
What you get
Every row carries the job, the pay, the employer and the classification:
- The job:
title,company,location(withcity,region,country,postalCode,streetAddresswhere Indeed has them),workplaceType(remote, hybrid, onsite),jobTypeandjobTypes,jobLevelwhen Indeed tags one (entry, mid, senior),datePosted(the employer's publish date) anddateOnIndeed(the day it reached Indeed),postedDaysAgo,jobUrlon Indeed,jobUrlDirecton the employer's site when the posting lives there,applyUrl,postedVia(the employer's site, an ATS, or Indeed itself), the fulldescriptionin Markdown, HTML or plain text. - The pay:
salaryMin,salaryMax,salaryInterval,salaryCurrency,salarySource(employer, or description when read from the text),salaryMinAnnual/salaryMaxAnnual,salaryMinUsd/salaryMaxUsd,salaryTextas the recruiter wrote it,payTypes(bonus pay, commission, tips, holiday pay). Indeed's own estimate lands inestimatedSalary*withhasEstimatedSalarywhen the API returns one, which in our measurements it rarely does. - Benefits, schedule, skills:
attributes(every label Indeed shows),benefits,schedule,skills(the requirement labels Indeed lists alongside),workSchedule. - The employer:
companyUrl(Indeed company page),companyWebsite,companyIndustry,companyNumEmployees,companyRevenue,companyCeo,companyLogo,companyHeaderImage,companyDescription,companyAddresses. - Classification:
department,seniority,jobCategory,employmentType,yearsExperienceMin/Max,visaSponsorship,educationLevel,tech,techCategories,emailsfound in the text. - Bookkeeping:
searchTerm(which of your terms found it),matchedLocation,sourceSearchUrl,dedupeKey,firstSeenAt(monitor mode),keywordMatchPercentwhen you score against keywords.
Salaries you can compare
The employer's stated pay goes to salary* with salarySource: "employer", as min, max, interval and currency, then
annualised (hourly x 2,080, daily x 260, weekly x 52, monthly x 12) and converted to USD with the day's rates, so a
Berlin posting in EUR and a Toronto one in CAD sort on one column. When the employer states nothing in the pay fields
but writes a range in the text, the range is read out and marked salarySource: "description". salaryText keeps
the pay exactly as the recruiter wrote it. Indeed's own estimate, the one its site shows under "Estimated", is a
separate thing: when Indeed's API returns it, it lands in estimatedSalary* and never in the employer's fields; in
our measurements the API returned it for none of the postings read, so count on the employer's pay, which 50 to 95
percent of postings state depending on the trade. requireSalary keeps only employer-stated pay.
Benefits, schedule, workplace
Indeed tags each posting with attribute labels: Health insurance, 401(k), Paid time off, Monday to Friday, Day shift,
Weekends as needed, Cash register, Forklift, Bilingual, Hybrid work, Remote, In person, Entry level. All of them are in
attributes; the ones that are benefits are in benefits, the ones about days and shifts in schedule, the pay
types (bonus, commission, tips) in payTypes, the requirement labels in skills, the level in jobLevel, and
workplaceType says remote, hybrid or onsite. remoteOnly uses Indeed's own remote filter first, then every row is judged again by its location, attributes
and text; a row with no remote evidence is removed before billing.
74 countries
country picks the Indeed site: usa (default), canada, uk, ireland, australia, new zealand, india, singapore, hong kong,
japan, south korea, taiwan, philippines, malaysia, indonesia, thailand, vietnam, pakistan, bangladesh, germany, france,
netherlands, belgium, luxembourg, switzerland, austria, italy, spain, portugal, denmark, sweden, norway, finland,
poland, czech republic, slovakia, hungary, romania, bulgaria, croatia, slovenia, greece, cyprus, malta, estonia,
latvia, lithuania, ukraine, turkey, israel, united arab emirates, saudi arabia, qatar, kuwait, bahrain, oman, egypt,
morocco, nigeria, south africa, brazil, mexico, argentina, chile, colombia, peru, ecuador, venezuela, uruguay, costa
rica, panama, china. Results come in the site's language; descriptions are delivered as published.
Paste a search URL
Copy the address bar from any Indeed search and put it in searchUrls. Keywords, place, radius, the date window
(fromage), remote, job type and experience level are read from it, and the country from the host
(uk.indeed.com, de.indeed.com). One search per URL, up to 20; every row says which URL found it in sourceSearchUrl.
Filters that never bill
Indeed applies its own date window, remote, job type and Indeed Apply filters before anything is read. Everything
else is applied here, after the rows are read and before anything is charged. A row with no evidence for a filter (no
date, no seniority cue) is kept; silence is not a mismatch. RUN_SUMMARY.filterRemoved shows the count per filter.
| Filter | Keeps |
|---|---|
requireSalary | employer-stated pay only (Indeed's estimate does not count) |
minSalaryUsd | annualised pay at or above the number |
requireTech | postings that mention any of the technologies |
excludeTitleKeywords / requireTitleKeywords | by words in the title |
excludeCompanies / targetCompanies | by employer, parent names included |
excludeCities | drops places you do not want inside a wide radius |
excludeAgencies | drops staffing and recruiting agencies |
maxAgeDays | by the employer's publish date |
experienceLevel | junior, mid, senior, lead, as classified from the title |
strictKeywordMatch | only postings whose title or text carries every word of your term |
remoteOnly | rows with remote evidence (Indeed's filter, then location, attributes, text) |
jobType | Indeed's job type, checked again against the posting |
Monitor mode: only what is new
onlyNew: true remembers what a search already delivered, in a key-value store in your own account, and later runs
deliver only postings not seen before. Schedule the run daily and the dataset is your feed of new Indeed jobs. Rows
seen before are not delivered and not charged. monitorName names the memory when you run several monitors.
Alerts
webhookUrl receives a digest when a run delivers rows: how many, the top titles and companies, the salary range,
links to the dataset. A Slack or Discord webhook gets a readable message; any other URL gets JSON.
Rows arrive page by page
Indeed answers 100 postings per request. Each page is enriched and delivered as it lands, so the first rows are in
the dataset within seconds and RUN_SUMMARY.waves says when each page arrived. Several terms and places are paged at
the same time, each until its share of results is met; when the filters leave the run short, the searches that still
have pages take turns until the target, and, if your own words run dry, the same role is searched under its other
names (a row found that way must carry the related title in its own title; expandTerms: false turns this off).
Every option
| Option | Default | What it does |
|---|---|---|
searchTerms | job titles or keywords, one search each (up to 10) | |
location | city, state, postal code or country as typed on Indeed; empty = the whole country | |
locations | more places; every term is searched in every place (up to 10 places) | |
country | usa | which Indeed site, by name (74) |
searchUrls | pasted Indeed search URLs; when given, the fields above are ignored | |
results | 200 | jobs to deliver per run, after deduplication and filters (1 to 10,000) |
postedWithinHours | Indeed's date window: 24, 72, 168 ... | |
remoteOnly | false | Indeed's remote filter plus the evidence check |
jobType | fulltime, parttime, contract, temporary, internship, perdiem, volunteer | |
indeedApplyOnly | false | only postings applied to through Indeed |
radiusMiles | 50 | distance around the place |
includeEstimatedSalary | true | deliver Indeed's estimate in the estimatedSalary* fields when the API returns one |
descriptionFormat | markdown | markdown, html or text |
requireSalary, minSalaryUsd, requireTech, excludeTitleKeywords, requireTitleKeywords, excludeCompanies, targetCompanies, excludeCities, excludeAgencies, maxAgeDays, experienceLevel, strictKeywordMatch | the filters above | |
resumeKeywords | score every row against these words (matchedKeywords, keywordMatchPercent) | |
sortBy | salary_desc or date_desc inside each delivered page | |
expandTerms | true | search related titles when your words leave the target short |
onlyNew, monitorName | false | monitor mode |
webhookUrl | alert digest | |
useApifyProxy, proxyConfiguration | Apify residential | Indeed refuses Apify's own addresses, so residential sessions are used |
How much does it cost?
$0.003 per job row delivered, on every plan. Nothing else is charged except Apify's standard Actor start.
| Run | Rows | Price |
|---|---|---|
| Default (200 rows) | 200 | $0.60 |
| A daily monitor that finds 30 new postings | 30 | $0.09 |
| A 1,000-row sweep | 1,000 | $3.00 |
| A salary study, 150 rows that state pay | 150 | $0.45, the rows without pay were never charged |
Compute and proxy traffic are covered by the row price. Set a maximum total charge on the run if you want a hard cap; rows beyond it are not delivered and not charged, and a notice row says how many were held back.
Use it from an AI agent, the API or an integration
The Actor is listed for agentic payments and works as an MCP tool through Apify's MCP server. From code:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("spool/indeed-scraper").call(run_input={"searchTerms": ["data engineer"], "location": "New York, NY", "results": 300})for job in client.dataset(run["defaultDatasetId"]).iterate_items():print(job["title"], job["company"], job["salaryMinUsd"], job["applyUrl"])
const { ApifyClient } = require('apify-client');const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('spool/indeed-scraper').call({ searchTerms: ['data engineer'], location: 'New York, NY' });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Schedule it, connect the dataset to Google Sheets, Make, Zapier or n8n through Apify's integrations, or point the alert webhook at Slack.
What it covers, honestly
- Indeed's matching is Indeed's. A search for "electrician" returns what Indeed ranks for it, including adjacent trades.
strictKeywordMatchkeeps only rows whose title or text carries your words;requireTitleKeywordsnarrows to the title. - Two dates.
datePostedis the employer's publish date;dateOnIndeedis the day the posting reached Indeed, which is whatpostedWithinHoursfilters on. They can differ by days for postings Indeed picks up from employer sites. - Indeed's pay estimate is rarely in this API's answer. The fields exist and fill when it is; do not plan on them. The employer's stated pay is what you get, on 50 to 95 percent of postings depending on the trade.
- Company rating and review counts are not part of this API answer and are not delivered.
- Remote evidence. On remote searches, rows that carry no remote cue in their location, attributes or text are removed before billing. Indeed's remote tag counts as a cue.
- Deep runs page 100 at a time; a 1,000-row search is ten requests per term. Very broad searches with heavy filters read more pages than they deliver;
RUN_SUMMARY.postingsScannedsays how many. - Pay ranges written in the text are read by rules and marked
salarySource: "description"; check them before you rely on them.
Is this legal?
The Actor reads publicly listed job postings that Indeed shows to anyone, without logging in, through the same API Indeed's app uses, paced through residential sessions. It stores what the posting says. Email addresses that appear in a posting's text are delivered as published; handle them under the law that applies to you. You are responsible for how you use the data, including Indeed's terms of use and the data protection rules of your jurisdiction.
FAQ
Why do I see titles I did not type? Indeed's own matching, or, when your words left the target short, related
titles of the same role. searchTerm on every row says which term found it; strictKeywordMatch or
expandTerms: false narrows it.
Why is the salary empty when Indeed's site shows one? What the site shows is Indeed's estimate, which its API
rarely returns; the salary* fields carry what the employer stated or wrote in the text, and salaryText the
recruiter's own words.
Can I get more than 1,000 rows? Yes, results goes to 10,000. Indeed returns at most about 1,000 postings per
search, so use several terms or places for more.
Does it work outside the US? Yes, 74 country sites by name or pasted URL. Salaries are converted to USD at the day's rates; the original currency is kept.
How fast is it? The first page lands in a few seconds; a 200-row run finishes in well under a minute; 1,000 rows
in a couple of minutes. RUN_SUMMARY.waves shows when each page arrived.
What if a run hits its time limit? It stops itself a margin before the limit, delivers what it had, writes its
summary and ends as succeeded with status: stopped-at-time-limit.
Changelog
1.0.0 — 2026-10-31. First release. Indeed through its own JSON API, 100 postings per request with full descriptions; employer pay annualised in USD, pay ranges read from the text, the recruiter's pay text kept; benefits, schedule, skills, pay types, level and workplace type from Indeed's attributes; company industry, size, revenue, CEO, website, logo and header image; where the posting came from; 74 countries; pasted search URLs; 14 filters that never bill; monitor mode; alert webhook; related-title fill with the title rule; page-by-page delivery. Measured: 200 rows in 4.8 s (default), 200 filtered remote rows with pay in 59 s, 100 UK rows in 7 s.
Support
Issues tab on this page, or the email on the spool profile. Bugs are fixed in days, with the fix in the changelog.
More from spool
- Job Board Scraper & API: one search across LinkedIn, Indeed, Glassdoor and 30 more sources, the employer's own posting attached.
- Job Search Scraper: live jobs straight from company career pages, 1,100 verified employer boards.
- Career Page Scraper & ATS Jobs API: Greenhouse, Lever, Ashby, Workday, SmartRecruiters and 12 more ATS platforms, no proxy.