Indeed Jobs Scraper avatar

Indeed Jobs Scraper

Pricing

from $0.02 / 1,000 jobs

Go to Apify Store
Indeed Jobs Scraper

Indeed Jobs Scraper

Scrape Indeed jobs in 60+ countries by keyword, location or URL, beyond the 1,000-job limit: title, full description, salary, location, job type, remote, company profile and rating. Export to JSON, CSV or Excel.

Pricing

from $0.02 / 1,000 jobs

Rating

0.0

(0)

Developer

Nice Dev

Nice Dev

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

3

Monthly active users

20 minutes ago

Last modified

Share

💼 What is Indeed Jobs Scraper?

Indeed Jobs Scraper extracts job postings from Indeed in 62 countries: title, full description, salary, location with GPS, job type, remote type, experience level and the employer's profile (website, size, revenue, sector, rating, reviews), for any keyword, place or search URL. It works as an Indeed API alternative: run it on a schedule, call it from your code, or plug it into Make, Zapier or n8n.

Type a keyword (software engineer) and a location, or paste any Indeed search URL, click Start, and download the jobs in JSON, CSV or Excel. Pick several countries, keywords and locations in one run, filter on the contract type, remote work, level, salary and date, or tick Only new jobs to monitor a market. No login, nothing to set up.

📋 What data can you extract from Indeed?

One item per job, 115 fields:

CategoryWhat you get
🏷️ Jobtitle, Indeed link, job key — Senior Software Engineer
🏢 Companyname, Indeed company page, website, logo, sector, size, revenue, founding year, CEO, headquarters, parent group, the sections of its company page — HubSpot
⭐ ReviewsIndeed rating and review count, ratings by theme (pay, culture, management…), CEO approval, work wellbeing, interview difficulty and length — 3.9 from 20,438 reviews
📍 Locationcity, state, county, postal code, street address, country, latitude and longitude — Jersey City, NJ 07310
💰 Salaryminimum, maximum, period (hour, month, year…), currency and the text Indeed shows, in the language of the country's site — $137,750 - $195,000 a year
🧭 Work typefull-time, part-time, contract…, remote / hybrid / on-site, experience level — hybrid
📝 Descriptionfull text, HTML or Markdown of the job, requirements, Indeed tags (skills, benefits, education, licences)
🕒 Dateswhen the employer published the job, when it appeared on Indeed, expiry — what the date filters read
🔗 Applyemployer or ATS page, Indeed Apply or not, openings, urgent and high-volume hiring, employer response rate
📞 Contacts (option)e-mails and phone numbers the employer wrote in the job text
🏭 Company rows (option)one row per employer: profile, open jobs now, new jobs in 24 hours / 7 days / 30 days, change since the previous run

Every field, with an example, is listed in the Output section below.

✅ Why use Indeed Jobs Scraper?

  • 🌍 62 Indeed countries in one run: several countries × several keywords × several locations, each search with its own cap.
  • 🎯 Filters applied by Indeed: job type, remote work, experience level, salary, date, language, radius — fewer pages to read, nothing to pay for the jobs left out.
  • 🧩 Rich rows: the full description, salary, GPS location and the employer's profile and ratings in every job.
  • 🔁 Nothing twice: a job found by several searches is saved — and charged — once.
  • 🔔 Monitoring built in: tick Only new jobs, schedule the Actor, and each run returns (and charges) only what it has never delivered before.
  • 🔌 API, scheduling, monitoring, integrations (Make, Zapier, n8n, Google Sheets…), proxy rotation and JSON/CSV/Excel export via the Apify platform.

🚀 How to scrape Indeed

  1. Create a free Apify account.
  2. Open Indeed Jobs Scraper, type a Search keyword (e.g. software engineer) and a Location (e.g. New York, NY), and pick the Country.
  3. Or paste your own Indeed URLs into Start URLs: any search results page (keyword, place, radius, date, sort and job-type filters are kept) or single job pages; or give Job keys.
  4. Set Max jobs (100 by default, 0 = no limit) — and Max jobs per search when you run several searches — then click Start.
  5. Download the dataset in JSON, CSV, Excel or via API.

💰 How much does it cost to scrape Indeed?

This Actor uses pay per event pricing: a price per 1,000 jobs saved plus a small fee per run start — the amounts are on the Pricing tab of this page. Filters Indeed does not offer are applied by the Actor on every job it reads: a job you keep costs its normal price, a job a filter drops costs a smaller filter fee (filter-check) — filtering never costs more than taking everything. Filters applied by Indeed itself (the Job filters section of the form) cost nothing for the jobs left out. Platform usage (compute, proxy) is included in the price.

⚙️ Input

{
"query": "software engineer",
"location": "New York, NY",
"country": "US",
"maxItems": 200
}

Several countries and keywords, only recent full-time jobs paying at least 60,000 a year, only the ones not delivered before:

{
"searchQueries": ["nurse", "teacher"],
"countries": ["GB", "IE"],
"jobTypes": ["fulltime"],
"minSalary": 60000,
"datePosted": "7d",
"maxItemsPerQuery": 50,
"onlyNew": true,
"stateKey": "nurses-uk"
}

Or with your own URLs and job keys:

{
"startUrls": [
{ "url": "https://www.indeed.com/jobs?q=nurse&l=Texas&fromage=7&sort=date" },
{ "url": "https://www.indeed.com/viewjob?jk=4f9a1c2b3d4e5f60" }
],
"maxItems": 500
}
FieldNotes
query, searchQueriesKeyword as typed on Indeed (software engineer, title:(nurse)); searchQueries adds more keywords (one search each). Empty = every job of the location. Ignored when startUrls is set.
location, locationsCity, state, region or postal code (New York, NY, Paris); locations adds more places. Every keyword is searched in every location (max 500 searches per run). Empty = the whole country.
country, countriesThe Indeed country site to search (US, GB, FR, DE… 62 countries); countries lists more: with country left on US, only the countries of the list are searched (put US in the list to include it), another country is added to them. Every keyword × location is searched in each (max 500 searches per run). With no keyword, location, URL, job key or company, the default country alone runs a 20-job example; any other country, or countries filled (for the whole US, put US in countries), reads every job of the country up to maxItems (onlyNew allowed).
startUrlsIndeed URLs of any country: search results pages (keyword, place, radius, age, sort and job-type filters kept; pagination automatic), company job pages (https://www.indeed.com/cmp/Hubspot/jobs: all the open jobs of that employer, or only those of its own keyword and place boxes: https://www.indeed.com/cmp/Hubspot/jobs?q=engineer&l=Boston) or single job pages (https://www.indeed.com/viewjob?jk=4f9a1c2b3d4e5f60).
jobKeysJob keys to read directly (4f9a1c2b3d4e5f60), on top of the keyword and location searches (empty them to read only these jobs): expired jobs are returned too, flagged as expired. Up to 10,000. The datePosted, jobTypes, remoteType, experienceLevels, minSalary / maxSalary and jobLanguage filters are checked on each job, also for a single job link of startUrls: a job that does not show the criterion is dropped and counted as filtered out (the pay is compared per year, so a pay by the day or the hour does not match); the radius and the location of a search cannot be read on a job and are not applied. A job link is read on the site of the link, a bare key on the Country site — on the first of countries when Country is left on United States and that list is filled: give the country of the job to get its pay.
companiesAll the open jobs of these employers: company names (Starbucks), website domains (starbucks.com) or employer keys (afd1466db269b253). Each entry is matched to the exact Indeed employer, never to a look-alike: a name with no exact match is skipped, and the log names the employers Indeed lists under that name (give the exact name, or paste the Indeed company page in Start URLs). Combined with the keywords and locations when they are filled; ignored when Start URLs are set.
maxItems, maxItemsPerQueryStop after this many jobs for the whole run, and for each search (0 = unlimited).
splitLargeSearchesIndeed shows at most 1,000 jobs per search. When a search has more, the Actor counts it by publication date (a counter call, free), cuts it into date slices and reads each one: nearly all of a large search (99.9 % measured on searches of 2,500 to 13,700 jobs) instead of the first 1,000. The log and the COVERAGE record of the key-value store give announced against collected jobs per search; a slice of one hour still above 1,000 jobs is read up to 1,000 and reported. Off = the first 1,000 only.
descriptionFormatWhich forms of the description to save: text_html, all (text, HTML and Markdown), text, html, markdown, none.
extractContacts, companySummaryExtra-charge options, both off by default (the events are on the Pricing tab). Contacts: the e-mail addresses and phone numbers the employer wrote in the job text are added to each job that has one, and only those jobs are charged (on 700 jobs read in the US, France and Germany, 19 % had an e-mail and 8 % a phone number). Company summary: one extra row per employer of the run, not counted in Max jobs and charged per row.
datePostedOnly jobs added to Indeed in this period: 24h, 3d, 7d, 14d, 30d, any.
jobTypesKeep jobs of ANY of these types: fulltime, parttime, contract, temporary, internship, permanent, fixedterm. Outside the USA the fixed-term contract Indeed shows as « Contract » (« CDD », « Befristeter Vertrag »…) is fixedterm: contract is the contractor, mostly in the USA, Canada and Australia.
remoteTypeWork arrangement as tagged by Indeed: any, remote, hybrid, onsite.
experienceLevelsKeep jobs of ANY of these levels: entry, mid, senior.
industriesSectors of the employer: a name (Healthcare) or an Indeed sector key (22VKN): names or keys in one run, not both.
minSalary, maxSalaryYearly pay bounds in the country's currency, Indeed's estimates included (0 = none).
radiusDistance around the location (25; 0 = the exact place).
radiusUnitUnit of the radius: miles or km.
jobLanguageOnly jobs written in this language: two letters (en, fr, de).
sortByrelevance or date (newest first).
postedAfter, postedBeforeDate the job was added to Indeed: 2026-09-01 (dates are read in UTC), or a period before now (7 days, 2 weeks, 1 month, 24 hours).
excludeKeywords, excludeCompaniesDrop the jobs whose title (or the cleaned-up title Indeed shows, displayTitle) contains one of these words, or whose company name as shown (companyName, its Indeed company page name companyProfileName, or its parent group parentCompanyName) does (case and accents ignored).
onlyWithSalaryDrop the jobs that show no pay.
applyMethodany, easyApply (Indeed Apply only) or external (the employer's or ATS page).
minCompanyRatingDrop the jobs of employers rated below this (out of 5, 4); unrated employers are dropped too.
onlyNew, stateKey, resetStateMonitoring: only the jobs never delivered under this memory key (nurses-uk); resetState forgets the memory.
AdvancedproxyConfiguration (Apify proxy by default, included in the price; the residential proxy is not available), maxConcurrency (lowered by itself to what the memory of the run holds: 5 at the default 512 MB, 17 at 1 GB), maxRequestsPerMinute, minRequestIntervalMs, maxRequestRetries, debugLog.

📦 Output

A real item, shortened:

{
"recordType": "job",
"id": "b08f834bb5fd1e8d",
"url": "https://www.indeed.com/viewjob?jk=b08f834bb5fd1e8d",
"title": "Senior Associate - Machine Learning Engineer",
"normalizedTitle": "machine learning engineer",
"occupations": [{ "key": "EHPW9", "label": "Technology Occupations" }],
"companyName": "JPMorganChase",
"companyProfileName": "JPMorganChase",
"companyUrl": "https://www.indeed.com/cmp/Jpmorganchase-2",
"companyWebsite": "https://www.jpmorganchase.com/",
"companyIndustry": "Banking & Lending",
"companySize": "10,000+",
"companyRating": 3.9,
"companyReviewCount": 20438,
"companyRatingHistogram": [1189, 1269, 4097, 6736, 7147],
"location": "Jersey City, NJ 07310",
"city": "Jersey City",
"regionCode": "NJ",
"country": "US",
"latitude": 40.728752,
"longitude": -74.03531,
"remoteType": null,
"isRemote": false,
"jobTypes": ["fulltime"],
"experienceLevel": "mid",
"salaryMin": 137750,
"salaryMax": 195000,
"salaryPeriod": "year",
"salaryCurrency": "USD",
"salaryText": "$137,750 - $195,000 a year",
"descriptionText": "JOB DESCRIPTION As a Senior Associate, Data Scientist / Machine Learning Engineer within our…",
"language": "en",
"publishedAt": "2026-10-05T05:00:00.000Z",
"dateOnIndeed": "2026-10-05T23:25:50.472Z",
"isExpired": false,
"applyUrl": "https://JPMorganChase.contacthr.com/153829834",
"isEasyApply": false,
"searchQuery": "software engineer",
"searchLocation": "New York, NY",
"searchUrl": "https://www.indeed.com/jobs?q=software+engineer&l=New+York%2C+NY",
"rank": 1,
"scrapedAt": "2026-10-06T00:52:01.531Z"
}

You can download the dataset in various formats such as JSON, HTML, CSV or Excel. A field Indeed does not give for a job is null (or an empty list), never missing.

All 115 fields

FieldsWhat you get
recordType, id, urljob, the job key, the Indeed link of the job on its country site
title, normalizedTitle, displayTitle, normalizedCategory, occupationsthe title, Indeed's standard title, its cleaned-up title, Indeed's own category of the job (techsoftware, mednurse, retail; searches only), Indeed's occupation categories
companyName, companyProfileName, companyKey, parentCompanyName, companyParentUrl, companyUrl, companyWebsite, companyLogo, companyHeaderImagethe employer as the job shows it, the name of its Indeed company page (the group's, for an establishment), its Indeed id, its parent group and the group's Indeed page, its Indeed page, website and images
companyIndustry, companySize, companyRevenue, companyFounded, companyCeo, companyStockSymbol, companyHeadquarters, companyDescription, companyBriefDescriptionthe employer's profile: Banking & Lending, 10,000+, more than $10B (USD), 1799
companyTier, companyClaimed, companyCeoPhoto, companyBrandColor, companySocialLinksthe Indeed account type, whether the company page is managed, CEO photo, brand colour, social links
companyRating, companyReviewCount, companyReviewCountInCountry, companyRatingWorkLifeBalance, companyRatingCompensationBenefits, companyRatingCulture, companyRatingJobSecurityAdvancement, companyRatingManagement, companyRatingHistogramIndeed's ratings out of 5, overall and by theme, the review count (all countries, and those written in the country of the site), the number of 1 to 5 star reviews
companyCeoApproval, companyCeoApprovalCount, companyRecommendYes, companyRecommendNoCEO approval (0 to 1) and its votes, who would and would not recommend the employer
companyWellbeingScore, companyWellbeingGrade, companyWellbeingResponses, companyHappinessScore, companyHappinessGradeIndeed's work wellbeing and happiness scores (0 to 100), grades and number of answers
companyCustomContents, companyInterviewDifficulty, companyInterviewExperience, companyInterviewProcessLength, companyInterviewResponsesthe sections the employer wrote on its company page (why join us, benefits: title, text, picture or video); how candidates rate the interview (EASY, MEDIUM, HARD; POOR, AVERAGE, EXCELLENT), how long hiring takes (A_WEEK…) and how many answered
location, city, region, regionCode, county, countyCode, neighborhood, postalCode, streetAddressJersey City, NJ 07310, Jersey City, New Jersey, NJ, Hudson County, 017…
country, countryName, latitude, longitudethe Indeed country site (US), its name, the coordinates (null for a job placed at « Remote »: Indeed gives it no real place)
remoteType, isRemote, jobTypes, experienceLevelremote, hybrid or onsite (a job placed at « Remote » is remote); fulltime, parttime, contract…; entry, mid or senior
salaryMin, salaryMax, salaryPeriod, salaryCurrency, salaryText, salarySource137750, 195000, year, USD, the pay as Indeed shows it, ESTIMATED when the pay is Indeed's estimate
attributes, employerAttributes, requirements, workSchedule, screenerQuestionsevery Indeed tag of the job (type, skills, benefits, education, licences), those the employer chose, the requirements the employer set, the schedule it wrote (Night), what it asks candidates to confirm before applying
descriptionText, descriptionHtml, descriptionMarkdown, languagethe full description as text, HTML and Markdown (the forms the Description format asks for), its language
publishedAt, dateOnIndeed, dateLastAnnotated, expiresAt, isExpired2026-10-05T05:00:00.000Z when the employer published it, when it appeared on Indeed (what the date filters read), when Indeed last processed it (searches only), expiry, expired or not
applyUrl, isEasyApply, hiringCount, isHighVolumeHiring, isUrgentHirethe employer or ATS page, Indeed Apply or not, number of openings, hiring flags
employerResponseRate, employerResponseDays, employerActivelyReviewing, sourceType, sourceName, refNumhow often and how fast the employer answers, whether Indeed says it actively reviews applications, who posted the job (EMPLOYER, RECRUITER), the source, the employer's own reference
emails, phonese-mails and phones written in the job text (with the Contacts option; empty lists otherwise)
openJobs, newJobs24h, newJobs7d, newJobs30d, openJobsChange, jobsInRunthe summary row of a company (with the Company summary option: the row has recordType company, the employer's fields above and these counters; null on a job)
searchQuery, searchLocation, searchUrl, rank, scrapedAtthe keyword, the place and the Indeed search that found the job, its position in it (1 = first), the extraction time

💡 Tips

How to get more results

Indeed shows at most 1,000 jobs per search (10 pages of 100). With Get past the 1,000-job limit on (the default) the Actor goes further by itself: it counts the search by publication date, cuts it into slices that each fit in Indeed's window, reads them newest first and saves a job found twice once — set maxItems to 0 for everything. The COVERAGE record of the run's key-value store says, per search, how many jobs Indeed announces and how many were collected. A search read with a cap of 1,000 or less is not cut. You can still add keywords, locations, a narrower radius or the job-type filters, one search each.

To follow one employer, give its name in companies (or paste its Indeed company page in Start URLs): the Actor finds the exact Indeed employer and reads all its open jobs, with the same slicing.

How to reduce costs

The price is per job, so the levers are maxItems, maxItemsPerQuery, the filters of the Job filters section (Indeed applies them: the jobs left out are not read and cost nothing) and onlyNew for recurring runs (you never pay twice for the same job). Choose descriptionFormat none for a list without the descriptions: the runs are lighter, the price per job is the same.

Several searches in one run

Fill searchQueries, locations and / or countries: the Actor runs one search per country × keyword × location (3 keywords × 4 cities × 2 countries = 24 searches, up to 500 per run). The single query, location and country fields still work and are added to the lists. A job found by several searches is saved — and charged — once. Set maxItemsPerQuery to give every search its own cap: without it the first searches can use up the whole maxItems budget. You can also paste several search URLs into startUrls: each one is a search of its own, with the same cap.

Monitoring: only the new jobs

Tick Only new jobs (onlyNew) and schedule the Actor. The first run returns everything; each later run skips the jobs already delivered: they are not saved and not charged. The memory lives in a named key-value store of your account (indeed-jobs-scraper-seen, up to 150,000 jobs per key) and is only updated with jobs that really reached the dataset, so a failed run never hides anything. Give each schedule its own stateKey (two schedules sharing a key would hide each other's jobs), and tick resetState once to start over. Searches are then read newest first, and a search stops once it meets 500 jobs in a row you already have. A job that does not pass a time-dependent filter yet (a relative "posted before" date) is checked again on the next run.

Filter by publication date

datePosted keeps the jobs added to Indeed in the last 24 hours, 3, 7, 14 or 30 days. postedAfter and postedBefore take a date (2026-09-01, the whole day is included, in UTC) or a period before now (7 days, 2 weeks, 1 month; via the API also 24 hours or a full ISO date-time). They read the date the job appeared on Indeed (dateOnIndeed); Indeed itself cuts the pages, and the Actor keeps the exact bounds. A job without a date is dropped as soon as a date bound is set. Filtered-out jobs are not saved and do not count in maxItems (each job the Actor itself drops costs the filter fee, see Pricing); the run summary tells how many were filtered. With postedAfter, searches are read newest first and stop at the first page that is entirely too old.

🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

🤖 Use with AI agents (MCP)

AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the Apify MCP server, billed to their Apify account like any run. It returns one item per Indeed job. Actor id: nice_dev/indeed-jobs-scraper; MCP server with this Actor only: https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/indeed-jobs-scraper.

Smallest input, for a cheap first call:

{
"query": "software engineer",
"location": "New York, NY",
"maxItems": 10
}

Key output fields: title, companyName, location, salaryText, jobTypes, remoteType, dateOnIndeed and url.

Cost: the price per 1,000 jobs plus the run-start fee, see the pricing section above. Cap each call with maxItems and, through the API, with the run option maxTotalChargeUsd.

❓ FAQ

The Actor only reads the job postings Indeed shows publicly to any anonymous visitor. It logs in to nothing. Results can contain personal data (a recruiter's name or e-mail written in a job text), which is protected by GDPR: do not store it without a legitimate reason. You are responsible for using the data in compliance with Indeed's Terms of Use and applicable law. This Actor is not affiliated with Indeed.

Does it need a login or a proxy?

No login. The proxy is included in the price: leave the default setting (the residential proxy is not available). A request Indeed turns away is retried at once on a new proxy session, up to 10 times on top of the retries (without a proxy, after a pause of 5 seconds, doubled at each retry up to 60 seconds).

Is the data safe to open in Excel or to show on a web page?

Titles and descriptions are the employers' own words, copied as they are. A text can begin with -, +, = or @ (a phone number, a title such as -20% today): Excel and Google Sheets may read such a cell of a CSV file as a formula or as a number. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import these columns as text. Every URL field holds an http(s) URL or null. descriptionHtml is the employer's own HTML, which the Actor does not sanitize: on a web page, escape every field like any text written by a stranger.

Known limitations

  • Indeed shows at most 1,000 jobs per search; the date slices recover nearly all of a large search (99.9 % measured on 3 searches of 2,500 to 13,700 jobs), not all of it (jobs added while the run goes on can fall between two slices). A slice of one hour above 1,000 jobs is read up to 1,000 and reported in COVERAGE. With sortBy relevance, a split search is read newest first.
  • A company name needs an exact match with an Indeed employer: « Amazon » has no employer of that exact name (give Amazon.com, or paste the company page). A run whose companies match none of them fails with the list of closest names.
  • E-mails and phones are what the employer wrote in the text: a phone number is kept only when the text says it is a phone number.
  • The labels (tags, sectors, pay text) are in the language of the country's site, as on Indeed (French on the French site); the pay of a job read by key is only given on the site of the job's own country, so give the country of the keys you read.
  • Salaries filtered by minSalary / maxSalary include the ones Indeed estimates; salarySource tells which are estimates.
  • industries given as names are matched on the employer's sector label, after the page is read; Indeed sector keys are filtered by Indeed.
  • onlyNew remembers job keys, not their content: a job whose text changed is not returned again.
  • Two runs sharing the same stateKey at the same time may both return the same new job.

A run that reaches its timeout stops itself about 45 seconds before it: no new page is asked, what it read is saved and, with onlyNew, remembered, and the run ends Succeeded with "Stopped before the run's timeout". Resurrect it to go on from there, or give the next run a longer timeout (Run options).

A run the platform stops without warning (out of memory)

  • Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the jobs already saved are skipped: none is delivered or charged twice, and maxItems still counts them.
  • With onlyNew, the memory is saved after each write (at most once every 2 seconds): resurrect the stopped run and the jobs it had saved meanwhile join the memory; leave it stopped for good, and the next run may return the jobs of its last 2 seconds once more.

Something doesn't work?

The last line of the log counts the jobs saved and filtered out, and the requests that failed after every retry. Those requests are listed, with the reason, in the FAILED_REQUESTS record of the run's key-value store. A run that saved nothing and had failed requests fails, and its last message gives the cause.

If Indeed changes its pages, you are told instead of paying for blank rows. A results page that counts jobs but gives none the Actor can read is an error (listed in FAILED_REQUESTS), never a quiet "No jobs found". If the first 20 jobs read all lack their title, date, company name or location, the run saves nothing more, stops and fails, and its last message names the missing field: at most those first jobs are charged. A job that postedAfter / postedBefore drops because it has no date at all counts among those 20. A run of fewer jobs (a scheduled onlyNew run that finds a few new ones, a small Max jobs) is checked at its end, from 5 jobs: its jobs are already saved, and the run fails with the missing field instead of ending green.

🛟 Support

Open an issue in the Issues tab with a link to your run: the run log and the FAILED_REQUESTS record of the key-value store show exactly which requests failed and why.