Indeed Jobs Scraper - Most Comprehensive
Pricing
from $0.04 / 1,000 jobs
Indeed Jobs Scraper - Most Comprehensive
π₯ ~$0.05/1K jobs π₯ Extract accurate, structured job data from Indeed. Get ALL page results, not just the first page. 60+ fields per job with pre-parsed salary, verified company profiles, GPS coordinates, and hiring signals. 54 countries. Fast, low cost
Pricing
from $0.04 / 1,000 jobs
Rating
4.3
(6)
Developer
Kai
Maintained by CommunityActor stats
39
Bookmarked
7.9K
Total users
1.3K
Monthly active users
1.4 hours
Issues response
2 days ago
Last modified
Categories
Share
Scrape Indeed job listings from 62 countries, with up to ~190 fields per job: full descriptions, parsed salaries, skills and certifications as structured tags, complete company profiles, and apply links. Rich mode adds hiring signals that other Indeed scrapers do not collect: reposts, employer responsiveness, hires needed, required and preferred skills, and sponsored placements.
Search Indeed by keyword and location, or look up known jobs by job key. Starting at $0.04 per 1,000 jobs.
Why this scraper?
| This scraper | Other Indeed scrapers | |
|---|---|---|
| Price per 1,000 jobs | $0.04 | $0.07-6 |
Hiring signals: employer responsiveness, hires needed, required or preferred requirements, resume type (rich) | Yes | Only a few return any of them |
| Skill and attribute codes as key and label pairs | Yes | A few, without the hiring signals |
| Company profile: CEO, revenue, size, industry, and rating | Yes | Most |
Working hours as minimum and maximum hours (rich) | Yes | None |
Employer branding reasons (rich) | Yes | None |
Indeed search expressions: title:, company:, and exclusions | Documented and tested | Not documented |
Sponsored placements, with every position where Indeed showed each job (rich) | Yes | A few return a sponsored flag |
| The sponsoring employer's ID, also when a sponsored job appears as an organic result | Yes | None |
Date, job type, and remote filters together (rich) | Yes | Some |
| Direct lookup | By job key, for active and expired jobs | A few, by job URL |
Use cases
Recruiting and staffing leads
Find companies that hire now, with their size, revenue, website, and hiring needs.
{"keyword": "title:(\"registered nurse\")","location": "New York, NY","country": "US","sort": "date","fromDays": "3","maxItems": 100,"searchMode": "rich"}
Use company.name, company.size, company.revenue, company.urls.website,
company.socialLinks, signals.numHires, and apply.url.
Job market research
Compare salaries, skills, benefits, and requirements by role and region.
{"keyword": "title:(\"data analyst\")","location": "New York, NY","country": "US","maxItems": 500}
Use salary.min, salary.max, salary.period, classification.skills,
benefits, requirements.educationLevel, and
requirements.experienceLevel.
Hiring and labor market analytics
Track who hires, how fast they respond, which roles they repost, and how many people they need. Run the same input on an Apify schedule, and compare the results over time.
{"keyword": "title:(\"software engineer\") -intern","location": "Seattle, WA","country": "US","sort": "date","fromDays": "7","jobType": "fulltime","maxItems": 100,"searchMode": "rich"}
Use signals.isRepost, signals.isLatestPost, signals.numHires,
signals.employerResponsive, signals.hiringInsights, and dates.onIndeed.
Rich results include sponsored jobs. To count only organic jobs, see
How rich mode works.
Recruitment advertising intelligence
See which employers pay to promote jobs, for which searches, at which result positions, and how often.
{"keyword": "nurse","location": "New York, NY","country": "US","maxItems": 100,"searchMode": "rich"}
Keep jobs where signals.isSponsored is true. Use
signals.sponsoredEmployerKey, meta.scrapingInfo.page,
meta.scrapingInfo.index, and company.brandingReasons. The
placements record lists every card that Indeed showed,
also repeated placements of the same job.
Job boards and aggregators
Publish fresh listings with full descriptions, parsed salaries, addresses, and coordinates.
{"keyword": "software engineer","location": "United States","country": "US","sort": "date","fromDays": "1","maxItems": 0}
Use title.text, description.html, salary.text, location, urls.apply,
and dates.onIndeed.
Job monitoring
Check whether known jobs are still open, with a
lookup by job key. Use signals.isExpired.
Choose how to find jobs
| Starting point | Input | Use it for |
|---|---|---|
| A job title, skill, or company, and a place | keyword and location | Find jobs in an area |
| Exact titles or companies | keyword with title:, company:, or, and - | Match only the jobs you mean |
| Known Indeed jobs | jobKeys | Get full data for active and expired jobs |
If you provide jobKeys, the Actor looks up those jobs. It then ignores the
search fields, the filters, and maxItems.
Choose a data depth
| Mode | Fields | Results per search | Best for |
|---|---|---|---|
basic (default) | ~165 | Up to 1,000 or more | Large searches, fastest |
detailed | ~170 | Up to 1,000 or more | Hiring insights at full search size |
rich | ~190 | Up to about 600, about half of them sponsored | The most data per job, and sponsored placements |
Rich mode returns jobs in the order that Indeed shows them, with the sponsored placements. See How rich mode works.
Every job includes (basic):
- Job: title, normalized title, full description as text and HTML, snippet, reference number
- Links: Indeed job URL, employer job URL, apply URL
- Classification: job types, occupations, primary occupation, skills, languages, and all Indeed attributes as key and label pairs
- Salary: salary text, parsed minimum, maximum, or exact amount, currency, period, and extras such as bonuses
- Benefits: benefit labels, such as health insurance, 401(k), and paid time off
- Work arrangement: remote flag, shifts, schedules, travel
- Location: full address, city, state, county, postal code, country, latitude, and longitude
- Company: name, industry, size, revenue, descriptions, website, logos, ratings and review counts, CEO, social links, and response rate
- Apply: Easy Apply flag, apply scopes
- Dates: posted date, date on Indeed, expiry date, age text
- Signals: expired, urgent hire, and high-volume hiring flags, and the sponsoring employer's ID
- Requirements: experience level, education level, certifications, and other labeled requirements
- Metadata: job source, language, locale, search keyword, search location, result page and position
Detailed adds, when Indeed supplies them:
- Hiring insights: candidates needed and hiring-event flag
- Employer-provided attributes and occupations
- Required documents, remote work type, and job photos
Rich adds everything in detailed, plus:
- Hiring signals: repost and newest-post flags, employer responsiveness, days since the employer last reviewed applications, hires needed, new-job flag, and hiring tags such as fair-chance hiring
- Requirements: skills and qualifications, each marked required or preferred, and physical requirements
- Working hours: minimum and maximum hours for each period
- Apply: whether Indeed Apply needs a resume
- Salary: Indeed's own salary parse and salary text
- Company: employer branding reasons, featured-employer flag, and parent company
- Locations: number of locations for the same posting
- Search placement: sponsored flag, and a placements record with every card that Indeed showed
- More benefits, job types, shifts, and schedules
Search for jobs
Start with a keyword and a location:
{"keyword": "registered nurse","location": "New York, NY"}
The Actor searches the US site and saves up to 20 jobs. Set maxItems to set
an upper limit. Indeed can return fewer jobs. Use 0 to remove the Actor
limit. Set searchMode to detailed or rich for more fields. See
Choose a data depth.
Match titles and companies
Plain keywords use broad matching and can include related roles. Use Indeed search expressions when title or company matching is important.
| Expression | Meaning |
|---|---|
"data engineer" | Exact phrase in the posting. |
title:(data engineer) | Both words in the title. |
title:("data engineer") | Exact phrase in the title. |
title:("data engineer" or "data scientist") | Either phrase in the title. |
nurse -travel | Include nurse and exclude travel. |
company:Google | Jobs for the specified company expression. |
Indeed supports and, or, not, exclusions, quotes, and parentheses. You
can combine them:
{"keyword": "title:(\"data engineer\" or \"data scientist\") -intern","location": "United States"}
Filter by date, job type, and remote work
{"keyword": "software engineer","location": "Seattle, WA","fromDays": "7","jobType": "fulltime","remote": "hybrid","searchMode": "rich"}
fromDays keeps the jobs that reached Indeed in the last 1, 3, 7, or 14 days.
It filters on dates.onIndeed.
In basic and detailed mode, fromDays replaces jobType and remote. Rich
mode applies all three filters.
A hybrid search can also return fully remote jobs, because Indeed can give
one job both labels. Indeed's matching is broad, so a job can also be missing
the requested job type or remote label. When the exact value matters, check
classification.jobType, workArrangement.isRemote, and
workArrangement.locationType.
Sort by date
Set sort to date to get the newest jobs first in basic and detailed mode.
In rich mode, the results keep Indeed's card order, and sponsored jobs keep
their places.
Search within a radius
{"keyword": "software engineer","location": "10001","radius": "25","radiusUnit": "miles","maxItems": 50}
The default radius is 35 miles. Set radiusUnit to km for kilometers.
Search another country
{"keyword": "Buchhalter","location": "Berlin","country": "DE","radius": "50","radiusUnit": "km"}
country selects the Indeed site. The code for the United Kingdom is UK.
See the input reference for all codes.
Look up known jobs
Use the job key (the jk value in an Indeed job URL), or the whole job URL:
{"jobKeys": ["5e5dafc2a80c214d"],"country": "US"}
- Lookups return full job data for active and expired jobs.
signals.isExpiredistruewhen Indeed has closed the listing. - Use the
countryof the Indeed site that shows the job. - A lookup ignores the search fields, the filters, and
maxItems. It returns a repeated key once and skips unknown keys. basicreturns the basic fields.detailedandrichadd the detailed fields. A lookup cannot return the other rich fields. Use a rich search to get them.
How rich mode works
Rich mode returns the jobs in the order that Indeed shows them in its search
results. meta.scrapingInfo.page and meta.scrapingInfo.index give the
position of each job.
Sponsored placements. Indeed selects them. They can fall outside the
keyword, the title expression, the location, and the filters. They can be more
than half of the results, and a search that matches no jobs can still return
them. They count toward maxItems. Only a rich search reports sponsored
placements: use signals.isSponsored from rich searches only.
Sponsoring employer. signals.sponsoredEmployerKey is Indeed's ID for the
employer that sponsors the job. It stays on the job in every search and in
lookups, also when the job appears as an organic result.
Repeated jobs. Indeed often shows the same job on several pages, for
example sponsored on page 1 and organic on page 8. The dataset keeps the job
once, at its first card, and signals.isSponsored describes that card. The
placements record lists every card.
Organic jobs only. Keep the jobs where signals.isSponsored is false.
This filter also removes the few jobs that Indeed showed first as sponsored and
later as organic. For the exact organic set, keep the jobs that have a
placements row with sponsored set to false.
Result range. Indeed limits how many search results it shows, and it repeats jobs across them. A broad rich search therefore gives about 600 unique jobs, and about half of them are sponsored.
No rich results. When a rich search finds no jobs, the Actor returns basic-mode jobs for the same search and logs a warning. These jobs have no rich fields, and the placements record has no rows.
Input
A search uses keyword, location, or both. A lookup uses jobKeys.
Input reference
| Parameter | Type | Default | Effect |
|---|---|---|---|
| keyword | string | empty | Job title, skill, company, or search expression. See Match titles and companies. |
| location | string | empty | City, state, postal code, or other location text. |
| country | country code | US | Indeed country site. See the codes below. |
| maxItems | integer, 0 or more | 20 | Upper limit on saved jobs. Indeed can return fewer. 0 removes the Actor limit. |
| searchMode | basic, detailed, or rich | basic | Data depth. See Choose a data depth. |
| sort | relevance or date | relevance | Result order. Rich mode keeps Indeed's card order. |
| fromDays | "1", "3", "7", or "14" | any time | Keeps jobs that reached Indeed in the last N days. In basic and detailed mode, it replaces jobType and remote. |
| jobType | fulltime, parttime, contract, temporary, or internship | any type | Employment type. |
| remote | remote or hybrid | any | Work arrangement. hybrid can also return fully remote jobs. |
| radius | string with a number | "35" | Search distance from location. |
| radiusUnit | miles or km | miles | Unit for radius. |
| jobKeys | string[] | [] | Indeed job keys to look up. A lookup ignores the search fields, the filters, and maxItems. |
| proxyConfig | object | {"useApifyProxy":true} | Connection settings for the run. Keep the default. Without a proxy, most runs fail or return no jobs. |
Allowed country codes:
US, UK, CA, AU, IN, DE, FR, JP, BR, MX, IT, ES, NL, BE, CH, AT, SG, HK, IE, NZ, AR, BH, CL, CN, CO, CZ, DK, FI, GR, HU, ID, IL, KW, LU, MY, MA, NO, OM, PE, PH, PL, PT, QA, RO, SA, ZA, KR, SE, TW, TR, UA, AE, VE, VN, CR, EC, EG, NG, PA, PK, TH, UY.
Output
Each Dataset item is one job. Every documented field is present in every job.
When Indeed does not supply a value, the field is null, [], or {}. A rich
search also saves a placements record.
Sample rich job
This redacted rich-mode job is from Visa in Bellevue, WA. Long arrays and maps keep a few items. Square brackets mark values removed from the documentation. It is not a saved Dataset item.
Field reference
| Field | Type and contents |
|---|---|
id | string. Indeed job key. |
refNum | string or null. The job's reference number. |
title | object. text is a string; normalized is a string or null. |
urls | object. indeed is a string. external, apply, and clickTracking are strings or null. |
description | object. text and html are strings or null. |
snippet | string or null. |
classification | object. Contains the classification fields in the rows below. |
classification.jobType | string[]. |
classification.occupations | object with dynamic string keys and string labels. |
classification.primaryOccupation | {key: string, label: string} or null. |
classification.occupationMostLikelySuid | string or null. |
classification.skills, classification.languages | Array of {key: string, label: string} objects. |
classification.attributes | object. all is a dynamic string-to-string map. employerProvided is an array of {key: string, label: string} or null. |
classification.employerProvidedOccupations | Array of {key: string, label: string} objects or null. |
workArrangement | object. isRemote is boolean. locationType, remoteWorkType, and workSchedule are strings or null. shift, schedule, and travel are string arrays. remoteAttributes and workingSystem are arrays of {key: string, label: string}. |
workArrangement.workingHours | object or null. displayType, period, and source are strings; minimumHours and maximumHours are numbers. |
salary | object. text, minCents, maxCents, exactCents, currency, period, source, and detailed are strings or null. min, max, and exact are numbers or null. estimated is boolean. extras is string[]. |
salary.extracted | {min: number, max: number, type: string} or null. |
salary.snippet | {currency: string, source: string, text: string} or null. |
benefits | string[]. |
socialInsurance | object with dynamic string keys and string labels. |
apply | object. url, indeedApplyKey, and resumeType are strings or null; isEasyApply is boolean; scopes is string[]; organicApplyStarts is a number or null. |
location | object. formatted, formattedShort, fullAddress, city, state, stateName, admin2Code, admin2Name, admin3Code, admin3Name, admin4Code, admin4Name, postalCode, streetAddress, country, and countryName are strings or null. latitude and longitude are numbers or null. |
locationCount | number or null. |
company | object. Contains the company fields in the rows below. |
company text and list fields | name, key, sourceName, tier, industry, size, revenue, briefDescription, fullDescription, brandColor, stockSymbol, and phone are strings or null. sectors, customContents, and addresses are string arrays. brandingReasons is string[] or null. |
company flags | subsidiaryOptOut and featuredEmployer are booleans or null. |
company.urls | object. website and indeed are strings or null. |
company.logos | object. square, rectangular, header, header1960x400, and headerAltText are strings or null. squareSizes is {url64: string, url96: string, url128: string, url256: string} or null. |
company.ratings | object. overall, count, and reviewCount are numbers or null. count is the number of star ratings; reviewCount is the number of written reviews. They often differ. |
company.ceo | {name: string or null, photoUrl: string or null} or null. |
company.socialLinks | object. facebook, twitter, and instagram are strings or null. |
company.responsiveness | object or null. averageResponseTimeDays, responseRate, and lastActivityTimeInDays are numbers or null; isActivelyReviewed is boolean or null. |
company.parentEmployer | object or null. name and key are strings; indeedUrl is a string or null; subsidiaryOptOut is boolean or null. |
photos | string[] or null. Job-level image URLs. |
dates | object. posted, onIndeed, validThrough, and age are strings or null; postedToday is boolean. |
signals | object. isExpired, isUrgentHire, and isHighVolumeHiring are booleans. sponsoredEmployerKey is a string or null. isSponsored, isBrandedJob, isRepost, isLatestPost, isPlacement, isNew, employerResponsive, and jobPageExists are booleans or null. applyCount and numHires are numbers or null. hiringTags is string[]. |
signals.matchScores | Array of {key: string, value: string} objects. |
signals.hiringInsights | object or null. numOfCandidates is a number or null; employerLastReviewed and recurringHireText are strings or null; isHiringEvent is boolean. |
requirements | object. certifications, qualifications, physicalRequirements, eligibility, ageRequirement, and experienceDuration are string arrays. experienceLevel and educationLevel are strings or null. |
requirements.attributes | Array of {key: string, label: string, provenance: string, requirementStrength: string} objects or null. |
requiredDocuments | Array of {key: string, label: string} objects or null. |
meta | object. source is a string or null; language, locale, and scrapedAt are strings; workSetting is string[]. |
meta.feed | {isDradis: boolean, sourceType: string or null}. |
meta.search | object. keyword and location are strings or null. |
meta.scrapingInfo | {page: number, index: number}. |
Placements record
A rich search saves the record PLACEMENTS in the run's default key-value
store. The run's Output tab links to it. The record lists every card that
Indeed showed for the saved jobs, in page order. A job has one row for each
card, so a job that Indeed showed three times has three rows.
{"placements": [{ "jobKey": "5e5dafc2a80c214d", "page": 1, "index": 0, "sponsored": true },{ "jobKey": "5e5dafc2a80c214d", "page": 8, "index": 3, "sponsored": false }]}
| Field | Type and contents |
|---|---|
jobKey | string. The id of a job in the dataset. |
page | number. 1-based search result page. |
index | number. 0-based position on the page, including sponsored placements. |
sponsored | boolean. Whether this card was a paid placement. |
- The first row of a job matches its
meta.scrapingInfoandsignals.isSponsored. - The rows end at the card that reached
maxItems. A job that is not in the dataset has no rows. - The record covers the search results that the run collected. A run that stops early keeps the rows of the jobs that it saved.
- Basic mode, detailed mode, and lookups do not save the record.
Search and field limits
How many jobs can I collect?
maxItems is an upper limit, not a required result count. Indeed can return
fewer jobs. Set maxItems to 0 to remove the Actor limit. The run then ends
when Indeed has no more results. A basic or detailed search returns up to 1,000
or more jobs. A rich search returns up to about 600, about half of them
sponsored.
When you set a maximum cost per run, the run saves the jobs that this cost pays for and then ends as succeeded. A lookup then checks only the first job keys that the cost pays for. The run's status message tells you when this happens.
Why are some fields empty?
Indeed does not show all fields on every job. Some rich jobs do not have every rich field. In detailed mode, a job can have only the basic fields when extra detail is unavailable.
Can a job disappear after I collect it?
Yes. Indeed can change or remove listings at any time. Use a lookup to check whether a job is still open.