Indeed Fast Job Scraper: Annual Salary & Change Tracking avatar

Indeed Fast Job Scraper: Annual Salary & Change Tracking

Pricing

from $2.50 / 1,000 job listings

Go to Apify Store
Indeed Fast Job Scraper: Annual Salary & Change Tracking

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

Ace

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

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 actorTypical 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"
}
FieldTypeDefaultNotes
queriesarrayโ€”Required. Search terms; results merged and de-duplicated
countrystringus20 Indeed country sites supported
locationstringโ€”City, state or postal code
locationsarray[]Several locations; every search term is run against each
radiusinteger0Miles from location
jobTypestringanyfulltime, parttime, contract, temporary, internship
sortstringrelevanceOr date for newest first
postedWithinDaysinteger00 = no limit
maxResultsinteger200Your budget cap โ€” billing is per job returned
minAnnualSalaryinteger0Filters on the normalized annual figure
requireSalarybooleanfalseDrop listings with no pay information
remoteOnlybooleanfalseRemote and hybrid roles only
minCompanyRatinginteger01โ€“5; unrated employers are dropped when set
excludeAgenciesbooleanfalseScreen out recruiters and staffing firms
titleMustIncludearray[]Title must contain one of these
titleMustExcludearray[]Title must contain none of these
modestringsnapshotOr watchlist for change tracking
watchlistNamestringdefaultNames the saved baseline
fetchSurfacestringautoAdvanced โ€” 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 run
  • removed โ€” postings that disappeared (usually filled or expired)
  • repriced โ€” postings whose salary band moved, with previousAnnualSalaryMin and salaryDelta
{
"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 isSponsored flag 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/salaryMax and salaryPeriod are always included so you can recompute.
  • Salary is only present when Indeed shows it. Roughly 80% of listings carry pay data; requireSalary drops 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 queries is run against every entry in locations, 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.