Indeed Fast Job Scraper: Annual Salary & Change Tracking
Pricing
from $2.50 / 1,000 job listings
Indeed Fast Job Scraper: Annual Salary & Change Tracking
Indeed job listings scraper with 50+ fields per job. Pay normalized to an annual salary so hourly and salaried roles filter together. Structured location, sponsored-vs-organic flag, employer hiring signals, remote filter and change tracking. Clean JSON hiring data.
Pricing
from $2.50 / 1,000 job listings
Rating
0.0
(0)
Developer
Ace
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
๐ฐ Indeed Jobs Scraper - Annual Salary & Change Tracking
Scrape Indeed job listings into clean JSON with 50+ fields per job. Every pay rate is converted to an annual salary, so an hourly contract and a salaried role can be filtered and ranked against each other โ something Indeed itself will not do for you.
Built for hiring data, job market analysis, recruitment research and lead generation. Works as a jobs API: run it on a schedule and pull structured employment data straight from the dataset.
Search several job titles in one run (results de-duplicated automatically), filter by what a job really pays, screen out staffing agencies, and re-run on a schedule to get only what changed.
What makes this different
| This actor | Typical Indeed scraper | |
|---|---|---|
| Salary normalized to annual | โ hourly/daily/weekly/monthly โ yearly | โ raw, mixed periods |
| Filter by minimum annual pay | โ | โ |
| Multiple search terms per run | โ merged + de-duplicated | โ one term |
| Company rating filter | โ | โ |
| Exclude staffing agencies | โ | โ |
| Change tracking between runs | โ new / removed / repriced | โ |
| Title include / exclude rules | โ | โ |
Why normalizing salary matters. Indeed quotes pay in whatever period the employer
picked. A search that returns "$52 an hour", "$4,800 a month" and "$95,000 a year"
gives you three numbers that cannot be compared, sorted, or filtered. This actor
converts all of them to an annual figure first, so minAnnualSalary: 120000 means
what you think it means.
Input
Only queries is required.
{"queries": ["software engineer", "backend engineer"],"country": "us","location": "Austin, TX","radius": 25,"sort": "date","postedWithinDays": 7,"maxResults": 50,"minAnnualSalary": 120000,"requireSalary": true,"excludeAgencies": true,"minCompanyRating": 3.5,"mode": "snapshot"}
| Field | Type | Default | Notes |
|---|---|---|---|
queries | array | โ | Required. Search terms; results merged and de-duplicated |
country | string | us | 20 Indeed country sites supported |
location | string | โ | City, state or postal code |
locations | array | [] | Several locations; every search term is run against each |
radius | integer | 0 | Miles from location |
jobType | string | any | fulltime, parttime, contract, temporary, internship |
sort | string | relevance | Or date for newest first |
postedWithinDays | integer | 0 | 0 = no limit |
maxResults | integer | 200 | Your budget cap โ billing is per job returned |
minAnnualSalary | integer | 0 | Filters on the normalized annual figure |
requireSalary | boolean | false | Drop listings with no pay information |
remoteOnly | boolean | false | Remote and hybrid roles only |
minCompanyRating | integer | 0 | 1โ5; unrated employers are dropped when set |
excludeAgencies | boolean | false | Screen out recruiters and staffing firms |
titleMustInclude | array | [] | Title must contain one of these |
titleMustExclude | array | [] | Title must contain none of these |
mode | string | snapshot | Or watchlist for change tracking |
watchlistName | string | default | Names the saved baseline |
fetchSurface | string | auto | Advanced โ see Cost control below |
Output
One row per job. This is a real record from a live run:
{"recordType": "job","jobKey": "7ed4a2ce361aab9c","title": "Java Developer","company": "Pyramid Consulting, Inc","companyRating": 4.1,"companyReviewCount": 251,"location": "Columbus, OH 43215","isRemote": false,"remoteType": null,"remoteLabel": null,"jobTypes": ["Contract"],"salaryMin": 50,"salaryMax": 51,"salaryPeriod": "HOURLY","salaryCurrency": "USD","annualSalaryMin": 104000,"annualSalaryMax": 106080,"annualSalaryEstimated": true,"postedAt": "2026-01-23T06:00:00.000Z","postedRelative": "30+ days ago","urgentlyHiring": false,"easyApply": true,"expired": false,"snippet": "Design and develop Java-based applications...","query": "software engineer","url": "https://www.indeed.com/viewjob?jk=7ed4a2ce361aab9c"}
Note annualSalaryEstimated: true โ that role is quoted hourly, and $104,000 is the
full-time-equivalent conversion, not a figure the employer published. Yearly-quoted
roles come back with the flag false.
Watchlist mode
Set mode: "watchlist" and schedule the run. The first run captures a baseline and is
free โ it reports no changes because there is nothing to compare against yet. Every
run after that returns only:
newโ postings that appeared since the last runremovedโ postings that disappeared (usually filled or expired)repricedโ postings whose salary band moved, withpreviousAnnualSalaryMinandsalaryDelta
{"recordType": "change","changeType": "repriced","title": "Senior Backend Engineer","company": "Example Corp","annualSalaryMin": 165000,"previousAnnualSalaryMin": 150000,"salaryDelta": 15000,"url": "https://www.indeed.com/viewjob?jk=..."}
Use different watchlistName values to track several searches independently.
Cost control
Billing is pay per event โ you are charged only for job rows you actually receive. Error rows, the watchlist baseline, and "no changes" results are free.
maxResults is a hard budget cap: the run stops once it is reached.
Pricing is tiered by your Apify plan โ $0.004 per job on the Free plan, falling to $0.0015 on higher plans. You are charged only for job rows delivered to your dataset.
A search returns roughly 45 jobs per term + location, so a run over 4 combinations
returns ~180 jobs. maxResults is a hard cap: the run stops the moment it is reached.
fetchSurface selects which Indeed pages are fetched. auto (the default) tries the
lighter mobile pages using your own first search and falls back to desktop if they are
unavailable โ the page it fetches is kept, so choosing a surface costs no extra request.
What people use it for
- Salary benchmarking โ compare what roles actually pay across cities, using one normalized annual figure instead of mixed hourly/monthly/yearly quotes.
- Recruitment and hiring data โ track which companies are hiring, how many hires they need, and which employers respond to applicants.
- Job market analysis โ measure posting volume, remote share, and pay bands by region.
- Lead generation โ find employers actively spending on recruitment. The
isSponsoredflag separates paid placements from organic listings, which no other Indeed scraper exposes. - Job board feeds โ pull fresh listings on a schedule and diff them with watchlist mode.
Requirements and limitations
- A paid Apify plan with Unblocker access is required. Indeed is behind a Cloudflare JavaScript challenge. Measured directly: residential and datacenter proxies both return HTTP 403 even with full browser header and TLS fingerprinting. Proxy quality is not the issue โ the challenge requires executing JavaScript, which Apify Unblocker does. Without it this Actor cannot fetch anything.
- Indeed occasionally serves a challenge page with HTTP 200. The Actor detects this and retries the same offset up to three times rather than cutting the run short.
- Unblocker requests to Indeed fail transiently, and often. Measured over 15 consecutive requests to a single search URL on 2026-08-27, 47% returned a page and the rest came back as an empty HTTP 502 after 50-80 seconds; successes arrive in 2-4 seconds. The Actor therefore retries the first page of every search up to eight times before giving up, which is why an occasional run takes a few minutes longer than usual. If every attempt fails the run fails rather than reporting success with no jobs โ re-running it usually works.
- Annualized salaries assume full-time (40 hours/week, 52 weeks). A part-time
hourly role is annualized as if full-time. Raw
salaryMin/salaryMaxandsalaryPeriodare always included so you can recompute. - Salary is only present when Indeed shows it. Roughly 80% of listings carry pay
data;
requireSalarydrops the rest. - Agency filtering is heuristic name matching. It catches the large staffing firms and will miss small ones.
- Indeed serves only the first page of results to logged-out visitors. Page 2 onward
returns a "create an account or sign in" wall, verified directly across repeated trials.
In practice that means about 45 jobs per search term + location. This Actor gets
volume from breadth instead: every term in
queriesis run against every entry inlocations, and results are de-duplicated across the whole matrix. To collect ~450 jobs, use 10 term/location combinations rather than expecting 10 pages. - Data comes from Indeed's search cards, not individual job pages โ so you get summaries, not full job descriptions.
- Indeed can change its page structure at any time. The parser reads Indeed's embedded job data rather than CSS selectors, which is considerably more stable, but not immune.