Indeed Jobs Scraper - Salary, Company Rating & Post Date
Pricing
from $5.00 / 1,000 job postings
Indeed Jobs Scraper - Salary, Company Rating & Post Date
Track hiring trends and build recruiting lead lists from Indeed. Scrape postings into typed rows: title, company, company rating, exact posting date as a timestamp, and salary parsed to min/max with period. Open-ended ranges are handled instead of silently halving the pay.
Pricing
from $5.00 / 1,000 job postings
Rating
0.0
(0)
Developer
Henry Crawl
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Track hiring trends and build recruiting lead lists from Indeed. No Indeed API, no publisher account.
Salary arrives as salaryMin, salaryMax, salaryPeriod and a yearly estimate, posting age
as a real timestamp, and company rating as a number — not as English strings you have to parse
yourself.
Common uses: tracking who is hiring in a market, salary benchmarking, feeding a job board, and building recruiting prospect lists.
What you get per job
| Field | Example | Notes |
|---|---|---|
jobKey | d8123dc510d5b757 | Indeed's own id, use it to deduplicate across runs |
title | Warehouse Associate - Day Shift | |
company | Berlin Packaging | |
companyRating | 3.8 | Parsed to a number when Indeed shows it |
location | Chicago, IL | |
isRemote | false | |
salaryText | $18 - $22 an hour | Original string, kept for reference |
salaryMin / salaryMax | 18 / 22 | Numbers |
salaryPeriod | hour | hour, day, week, month, year |
salaryCurrency | USD | |
salaryYearlyEstimate | 41600 | Normalised so hourly and yearly postings are comparable |
jobType | Full-time | |
benefits | ["Health insurance","401(k)"] | The benefit chips Indeed shows on the card |
postedDaysAgo | 3 | 0 means posted today |
postedDateApprox | 2026-07-31 | Derived from the posting age |
isUrgentlyHiring, isEasyApply | true | |
snippet | Short description shown on the card | |
jobUrl | Direct link to the posting | |
searchQuery, searchLocation, pageNumber | Provenance of every row | |
indeedDomain, proxyCountry, scrapedAt | The exact context the data was captured in |
Input
{"queries": ["warehouse associate", "forklift operator"],"location": "Chicago, IL","indeedDomain": "www.indeed.com","proxyCountry": "US","datePosted": "last_3_days","jobType": "full_time","maxJobs": 1000}
Or paste Indeed search URLs directly in startUrls.
Filters available: country site, location and radius, date posted, job type, remote only, minimum salary, and sorting by relevance or date.
Why salary comes back as numbers
A job feed is only useful if you can rank it. Hourly and yearly postings are not
comparable as strings, so salaryYearlyEstimate converts both to the same basis
(hourly × 2,080, weekly × 52, monthly × 12). The original salaryText is always kept
so you can audit any conversion.
Country matters
Indeed is country-specific in two independent ways. indeedDomain picks which
national site to search, and proxyCountry decides where the request appears to come
from — which affects both results and currency. They default to the United States.
Residential proxies are used by default: Indeed refuses datacenter IP ranges.
The result cap is real
maxJobs stops the run at exactly that number. The run also stops on its own if three
consecutive pages return nothing usable, so a layout change cannot quietly turn into a
long, expensive run.
Runs fail loudly, not silently
Every run writes a DIAGNOSTICS record with the block rate, bytes per item and the
fill rate of every output field:
{ "itemsExtracted": 500, "blockRate": "0%", "fieldCoverage": { "salaryMin": "62%", "company": "100%" } }
If nothing was extracted, or more than half the pages were blocked, the run is marked failed with the reason. An empty column that looks like data is worse than an error.
Typical uses
- Salary benchmarking by role, city and employer
- Tracking which companies are hiring, and how fast their postings turn over
- Feeding a niche job board or a recruiting pipeline
- Labour market research on posting volume and pay trends
Notes and limits
salaryMin,companyRatingandbenefitsonly appear where Indeed shows them, and are reported asnullelsewhere rather than guessed.postedDateApproxis derived from a relative age ("3 days ago"), so it is accurate to the day, not the hour.- Keep
maxConcurrencylow. Indeed authorises by session.
Support
If a field stops filling or you need a filter that is not exposed, open an issue on the actor page with the input you used.
FAQ
Do I need an Indeed API key? No. Indeed's publisher API is closed to new applicants; this reads public search pages instead.
How accurate is the salary?
It comes from Indeed's own embedded data, not from parsing the display string. One trap is
handled explicitly: Indeed encodes an open-ended range like "From $27.84 an hour" as
max: -1. Averaging that in would halve the figure, so the max is dropped instead of used.
Why do I get more jobs per page than Indeed shows?
Indeed paints 16 cards but embeds the full result set as JSON — 39 rows on a typical page.
This actor reads the JSON, so you get all of them, deduplicated on jobKey.
Can it get applicant contact details? No. It reads public job postings only.
Indeed shows "30+ days ago" — how do I get the exact posting date? Indeed's relative labels round hard: "30+ days ago" covers everything from five weeks to a year, and "Active 3 days ago" is a bump, not a first-published date. This actor returns the absolute date alongside the label, so you can sort, filter and diff runs without guessing. That matters most when you are tracking how long a role has been open, or deduplicating against a previous run — relative strings are not comparable between two scrapes taken on different days, and treating them as if they were is how the same job ends up counted as new every week.
How do I get an Indeed API key? For most people, you do not. Indeed's job-search API is partner-only — access goes to ATS vendors, job boards and similar integrations through a commercial agreement, and individual developers asking for a key to pull listings are generally not the audience. That is why so many "Indeed API" search results are third-party services rather than Indeed itself. This actor reads Indeed's public search pages instead, so there is no key to apply for and nothing to be approved for; you need only an Apify account.
What does the Indeed API cost, and is this cheaper? Indeed does not publish a self-serve price because it is not a self-serve product — the cost is whatever a partnership agreement says. This is priced per row of output instead, so a small run costs a small amount and you can measure it before committing. The comparison worth making is not price against price but access against access: one requires a business relationship, the other starts working immediately.
Can I scrape Indeed job postings with Python?
You can, and the hard part is not the parsing — it is that Indeed answers automated requests
with a challenge page rather than results, so a plain requests script tends to work in testing
and fail in production. If you would rather not maintain that, start this actor from Python with
the apify-client package and read the dataset it produces; the rows come back as JSON with
absolute posting dates rather than "30+ days ago" strings.
Where can I get a job postings dataset? The free ones on Kaggle and GitHub are snapshots, and job data goes stale faster than almost any other kind — a posting that was open when the file was exported may have been filled months before you download it. That is fine for practising analysis and wrong for anything that acts on the data. This produces a current dataset instead: give it the queries and locations you care about, and you get rows with absolute posting dates, salary where Indeed publishes one, and the provenance of every row, generated the day you need it. Re-running it on a schedule is what turns it into a time series rather than a snapshot.
Can I build a job postings database that stays up to date? Yes, and the field that makes it possible is the absolute posting date rather than Indeed's "30+ days ago" label — relative strings are not comparable between two runs taken on different days, so a database built on them counts the same job as new every week. Keep the job URL as your key, store the absolute date, and each run either adds a genuinely new posting or confirms one you already have. Scheduling that on Apify is a few clicks and needs no code.
Related scrapers
The other half of the hiring picture, and the marketplace tools built the same way:
- LinkedIn Jobs Scraper — run both and deduplicate on company plus title to see which roles are posted in both places.
- eBay Scraper - Listings, Sellers & Sold Price Check — real sold prices and sale dates from public listing pages.
- eBay Seller Scraper — a sellers entire public inventory.
- Amazon Product Scraper — prices and demand signals with currency checked per row.