Indeed Jobs Scraper
Pricing
$1.00 / 1,000 results
Indeed Jobs Scraper
Search public Indeed job listings by title, location, and posting date. Export job, employer, pay, requirements, benefits, and description data.
Pricing
$1.00 / 1,000 results
Rating
0.0
(0)
Developer
MLG Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Search public Indeed job listings by title, keywords, and location, then export the results as structured JSON or CSV. This Indeed jobs scraper provides a search based alternative to manually opening individual job cards when you need titles, employers, locations, pay ranges, requirements, benefits, and links in one dataset.
The scraper reads the structured job information included in public search pages. One search can return dozens of listings, and you can enter additional titles to collect more jobs in the same location. Results are deduplicated by listing identifier. A description flag tells you whether the text is a complete job description or the shorter excerpt shown on the search page.
What data can you extract from Indeed?
Each row represents one distinct public job card. The following fields are returned for every row, with null or an empty list where the public page does not supply a value. Dates are UTC timestamps. Pay numbers retain the period reported by the listing; an hourly amount is not converted into an annual salary.
| Field | Description | Example |
|---|---|---|
key | Listing identifier used for deduplication | 8c543eb0a29e5ce3 |
url | Direct Indeed listing address | https://www.indeed.com/viewjob?jk=8c543eb0a29e5ce3 |
title | Job title | Python Developer |
jobUrl | Original employer posting address, when exposed | null |
datePublished | Published time in UTC | 2026-08-27T05:00:00.000Z |
dateOnIndeed | Listing creation time in UTC | 2026-08-27T15:49:42.212Z |
expired | Whether the card says the job is expired | false |
isUrgentHire | Urgent hiring flag | false |
isHighVolumeHiring | High volume hiring flag | false |
language | Job language when detail data includes it | en |
companyName | Employer displayed on the card | An employer name |
companyUrl | Public employer profile when available | A profile address |
companyRating | Displayed employer rating | 3.9 |
companyReviewCount | Displayed employer review count | 120 |
location | Full location line | New York, NY 10039 |
city | City, if identified | New York |
state | State or region, if identified | NY |
postalCode | Postal code, if provided | 10039 |
countryCode | Country code from the card | US |
isRemote | Whether the listing is explicitly remote | false |
remoteType | Remote or hybrid classification | REMOTE_HYBRID |
salaryMin | Lower displayed pay bound | 65 |
salaryMax | Upper displayed pay bound | 90 |
salaryUnit | Pay period | HOURLY |
salaryCurrency | Pay currency | USD |
salaryText | Pay text as shown | $65 - $90 an hour |
jobTypes | Employment type labels | ["Contract"] |
benefits | Benefit labels found on the card | [] |
skills | Visible requirement labels other than degrees | A list of labels |
education | Visible degree or diploma requirements | ["Bachelor's degree"] |
attributes | All visible requirement labels | A list of labels |
occupations | Occupation identifiers when detail data includes them | [] |
descriptionText | Plain text from a full description or a card excerpt | Description text |
descriptionHtml | Source markup for that description or excerpt | HTML text |
descriptionIsFull | Indicates whether the description is complete | true |
applyUrl | Application address supplied in the card | An application address |
sponsored | Whether the card is marked sponsored | false |
searchTitle | Search term that surfaced the job | Python developer |
searchLocation | Location entered for that search | New York, NY |
The descriptionIsFull field is especially useful for downstream processing. The public search page may include a full description for its initially opened listing, while other cards expose excerpts. Check this flag before treating descriptionText as a complete posting. The same distinction applies to descriptionHtml. An empty benefits list means no benefits were surfaced in that card; it does not establish that the employer offers none.
How to scrape Indeed jobs
- Enter a job title or keyword phrase in
title. Use terms that a job seeker would type into search, such as a role or specialty. - Enter a city, region, postal code, or remote search term in
location. Select the country site that matches the market you want to inspect. - Set
datePostedif recency matters, and setmaxItemsto the number of distinct jobs you want to keep. Add related searches inadditionalTitleswhen a single public page is insufficient. - Run the actor. The dataset contains one row for each distinct listing identifier returned by the public first pages.
- Download the dataset as JSON or CSV, or read it through the dataset API. Keep the listing key and URL if you plan to compare recurring runs.
A successful run can contain fewer jobs than maxItems. This limit is a ceiling, not a promise of a certain count. The available number depends on the search, country site, current public page, duplicate overlap, and access controls. Very narrow searches or recent date filters can produce few results.
Input
| Parameter | Type | Default | Description |
|---|---|---|---|
title | String | Required | Primary job title, keyword phrase, or employer query. |
location | String | Empty | City, region, postal code, or remote search term. |
country | String | us | Country site: us, ca, uk, au, de, fr, in, jp, or sg. |
datePosted | String | Empty | Restrict to the past 1, 3, 7, or 14 days. Empty means any date. |
maxItems | Integer | 100 | Maximum distinct rows across all search titles, from 1 to 1,000. |
additionalTitles | String array | Empty | Extra title or keyword searches in the same location. |
proxyConfiguration | Object | Automatic proxy | Optional proxy configuration. |
For a practical starting point, search one role in one city and request 30 rows:
{"title": "Python developer","location": "New York, NY","country": "us","maxItems": 30}
The first verified run with this input returned 30 distinct rows. Every returned row had a listing key, URL, title, employer name, location, publication date, and description text. That result is an example of one search at one point in time, not a guaranteed count for future runs. Search results and access conditions can change.
For broader coverage, enter adjacent role terms under additionalTitles. For example, a single location search for “data engineer” can be supplemented with “analytics engineer” and “data platform engineer.” The scraper removes duplicate listing keys across those searches. It does not combine results from different locations in one run; run the actor separately for each location when you need clean market comparisons.
Output example
This trimmed record is from the verified run. The employer name and description have been omitted from the example; the dataset includes them when present on the public page.
{"key": "8c543eb0a29e5ce3","url": "https://www.indeed.com/viewjob?jk=8c543eb0a29e5ce3","title": "Python Developer","datePublished": "2026-08-27T05:00:00.000Z","dateOnIndeed": "2026-08-27T15:49:42.212Z","expired": false,"location": "New York, NY 10039","city": "New York","state": "NY","countryCode": "US","remoteType": "REMOTE_HYBRID","salaryMin": 65,"salaryMax": 90,"salaryUnit": "HOURLY","salaryCurrency": "USD","salaryText": "$65 - $90 an hour","jobTypes": ["Contract"],"education": ["Bachelor's degree"],"descriptionIsFull": true,"sponsored": false}
The full row also contains the fields listed above. For this record, the pay range is hourly; it should not be compared directly with a yearly salary. A hybrid work classification is present even though isRemote is false, because hybrid and fully remote are separate classifications. The url points to the listing on Indeed. If the original employer posting address is not published in the search data, jobUrl remains null.
Use cases
- Recruitment research: Build a list of public openings for a role and location, then use listing URLs to review individual postings. Keep the publication date so older results do not appear newly posted in a later run.
- Salary analysis: Group listings by
salaryUnitandsalaryCurrencybefore comparing pay ranges. Analyze hourly and yearly listings separately, and exclude rows without numeric pay. - Regional hiring trends: Run the same title in several cities on a schedule. Compare distinct keys and publication dates to estimate which listings are newly visible in each market.
- Skills research: Count visible requirement labels across a set of roles. Treat those labels as information surfaced by the search card; they may not capture every qualification in the full posting.
- Job feed preparation: Export public listing titles, employers, locations, and links into a review queue. Use the source URL for any final verification before displaying or acting on a listing.
- Benefits and work arrangement tracking: Compare benefit labels and remote classifications where the public cards provide them. Keep empty lists and missing classifications separate from explicit negative values.
These uses work best when the search terms and locations are documented alongside the exported rows. The searchTitle and searchLocation fields provide that context within the dataset. When two terms surface the same listing, only the first encountered row is kept, so a job has one associated search term in that run.
How much does it cost to scrape Indeed?
The current result price is $1.00 per 1,000 delivered jobs, or $0.001 per job. Charges depend on rows actually written, not the requested maxItems. A run that delivers 30 jobs costs about $0.03 in result charges. One hundred delivered jobs cost about $0.10. A run reaching the 1,000 row input ceiling would cost about $1.00. These examples assume the current price and enough distinct public listings to reach each count.
A single search generally stops at its publicly available first page, so requesting 1,000 rows does not mean that 1,000 rows will be produced. To approach a higher limit, provide multiple relevant title searches or run separate locations. Duplicate cards do not produce additional rows. If a search yields no public cards, the run reports a failure rather than charging for a fabricated result.
Tips for best results
Use a recognizable role name and a specific location for the first run. Inspect the returned titles before expanding the search; broad terms can mix roles that are not directly comparable. When pay analysis is the goal, filter the exported rows by salaryUnit, salaryCurrency, and whether both numeric bounds are present. A displayed pay phrase may be more informative than the numeric fields for unusual compensation formats.
Use additionalTitles for nearby titles that describe the same hiring market. The scraper searches each term in order and deduplicates by key. If maxItems is reached during an earlier term, later terms are not queried. Put the most important title first. Run separate locations when you need each city's result count, because the additional title list shares one location setting.
For recent hiring monitoring, choose a datePosted filter and run the same input again later. Use the stable key to identify records already seen. The two date fields reflect different source timestamps: datePublished is the published time, while dateOnIndeed is the creation time included in the job card. Neither should be interpreted as the time you ran the actor.
Inspect descriptionIsFull before processing descriptions. Search snippets can contain formatting, shortened sentences, or highlighted search terms. The actor strips markup for descriptionText and preserves the source markup in descriptionHtml. For a full description requirement, select only rows whose flag is true, then review how many remain. The actor does not guess missing text or fill absent pay values.
Limits
Indeed can block requests or require sign-in. During development, some public search requests returned a block response, and one search succeeded after residential proxy session rotation. A later verified run returned 30 jobs. Access therefore varies between sessions. The actor first tries a lower cost proxy route, then rotates through residential sessions when blocked. A run can still fail if all attempts are blocked.
Anonymous page two searches redirected to a sign-in page in the observed test. The scraper reads the public first page for each search term and does not use account credentials. The first page returned several dozen distinct cards in the verified market, but the count is not fixed. maxItems applies across all terms; it cannot override the sign-in boundary. Some country sites may expose different layouts or restrictions, and only the United States search was verified in the golden run.
Job cards do not consistently contain full descriptions, employer profile details, original employer posting addresses, geocoordinates, or complete compensation. Fields such as jobUrl, companyUrl, and language can be empty. Employer ratings and review counts are only included where displayed. Benefits and requirements are the labels surfaced with the search card, not a complete interpretation of every posting. Listings may change, close, or disappear after extraction.
Use in automated workflows
A scheduled run can provide a fresh dataset for a review queue or market report. For example: “Collect up to 30 developer jobs in New York posted during the last seven days, then group the returned rows by pay period.” Another useful request is: “Search three related data roles in one city, deduplicate the listing keys, and show which records include explicit salary ranges.”
When connecting the dataset to another system, store key, url, and the source timestamps with each row. Apply your own checks for stale listings and handle nullable fields. If your workflow needs complete descriptions for every job or anonymous access beyond the first page, this actor's public search source may not meet that requirement.
FAQ
Is this limited to public data?
Yes. It uses job information exposed on public search pages and does not sign in or request private account data. Follow the site's terms and applicable privacy rules when storing, sharing, or using the results. Review each listing before taking action based on it.
Do I need to set up a proxy?
No for the default run. The actor configures a proxy automatically. You can supply proxyConfiguration if your environment requires a specific setup. Blocks can still occur, even after a proxy session changes.
How fast is a run?
The verified 30 row run completed in under one minute. Runtime depends on blocking, retries, the number of additional titles, and response size. A broad request may finish with fewer rows than requested because of the public page limit.
Can I schedule it and compare runs?
Yes. Keep the same title, location, country, and date filter between runs. Compare the key values to identify newly observed listings, and retain the timestamps for context. A missing key in a later run does not by itself prove that a job has closed.
Can I export the results to a spreadsheet?
Yes. Download CSV for spreadsheet import or JSON for a programmatic pipeline. Arrays such as benefits and skills may need separate handling in a spreadsheet, while JSON preserves them as lists.
Why is a field empty?
The public card may not supply it. Pay, benefits, employer ratings, profile links, and full descriptions are optional in the source. The actor keeps missing values as null or empty lists rather than inferring them. Check descriptionIsFull to distinguish a complete description from a snippet.
Why did I get fewer jobs than the limit?
The limit is a ceiling. Each term uses only its first public search page, and overlapping terms can return the same job. Narrow locations and date filters can further reduce the count. If the site blocks every attempt, the run fails with an error.
Integrations
Read the default dataset through the API, export it as JSON or CSV, or connect a scheduled run to a webhook. A downstream workflow can load those rows into a spreadsheet, database, or monitoring report. Use key for deduplication and preserve descriptionIsFull so downstream users know whether they received a complete description or a search excerpt.
Support
Open an issue on the Issues tab; we reply within 24h and add fields on request.