Indeed Jobs Scraper avatar

Indeed Jobs Scraper

Pricing

$1.00 / 1,000 results

Go to Apify Store
Indeed Jobs Scraper

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

MLG Data

Maintained by Community

Actor 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.

FieldDescriptionExample
keyListing identifier used for deduplication8c543eb0a29e5ce3
urlDirect Indeed listing addresshttps://www.indeed.com/viewjob?jk=8c543eb0a29e5ce3
titleJob titlePython Developer
jobUrlOriginal employer posting address, when exposednull
datePublishedPublished time in UTC2026-08-27T05:00:00.000Z
dateOnIndeedListing creation time in UTC2026-08-27T15:49:42.212Z
expiredWhether the card says the job is expiredfalse
isUrgentHireUrgent hiring flagfalse
isHighVolumeHiringHigh volume hiring flagfalse
languageJob language when detail data includes iten
companyNameEmployer displayed on the cardAn employer name
companyUrlPublic employer profile when availableA profile address
companyRatingDisplayed employer rating3.9
companyReviewCountDisplayed employer review count120
locationFull location lineNew York, NY 10039
cityCity, if identifiedNew York
stateState or region, if identifiedNY
postalCodePostal code, if provided10039
countryCodeCountry code from the cardUS
isRemoteWhether the listing is explicitly remotefalse
remoteTypeRemote or hybrid classificationREMOTE_HYBRID
salaryMinLower displayed pay bound65
salaryMaxUpper displayed pay bound90
salaryUnitPay periodHOURLY
salaryCurrencyPay currencyUSD
salaryTextPay text as shown$65 - $90 an hour
jobTypesEmployment type labels["Contract"]
benefitsBenefit labels found on the card[]
skillsVisible requirement labels other than degreesA list of labels
educationVisible degree or diploma requirements["Bachelor's degree"]
attributesAll visible requirement labelsA list of labels
occupationsOccupation identifiers when detail data includes them[]
descriptionTextPlain text from a full description or a card excerptDescription text
descriptionHtmlSource markup for that description or excerptHTML text
descriptionIsFullIndicates whether the description is completetrue
applyUrlApplication address supplied in the cardAn application address
sponsoredWhether the card is marked sponsoredfalse
searchTitleSearch term that surfaced the jobPython developer
searchLocationLocation entered for that searchNew 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

  1. 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.
  2. Enter a city, region, postal code, or remote search term in location. Select the country site that matches the market you want to inspect.
  3. Set datePosted if recency matters, and set maxItems to the number of distinct jobs you want to keep. Add related searches in additionalTitles when a single public page is insufficient.
  4. Run the actor. The dataset contains one row for each distinct listing identifier returned by the public first pages.
  5. 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

ParameterTypeDefaultDescription
titleStringRequiredPrimary job title, keyword phrase, or employer query.
locationStringEmptyCity, region, postal code, or remote search term.
countryStringusCountry site: us, ca, uk, au, de, fr, in, jp, or sg.
datePostedStringEmptyRestrict to the past 1, 3, 7, or 14 days. Empty means any date.
maxItemsInteger100Maximum distinct rows across all search titles, from 1 to 1,000.
additionalTitlesString arrayEmptyExtra title or keyword searches in the same location.
proxyConfigurationObjectAutomatic proxyOptional 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 salaryUnit and salaryCurrency before 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.