Indeed Scraper - Jobs, Salaries & Companies USA avatar

Indeed Scraper - Jobs, Salaries & Companies USA

Pricing

Pay per event

Go to Apify Store
Indeed Scraper - Jobs, Salaries & Companies USA

Indeed Scraper - Jobs, Salaries & Companies USA

Scrape Indeed.com US jobs: title, company, parsed salary, remote flag, location, skills. 30+ fields per job, HTTP-only. Filter by keyword, location, remote, salary minimum.

Pricing

Pay per event

Rating

0.0

(0)

Developer

deusex machine

deusex machine

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

Share

Indeed Scraper API — Jobs, Salaries, Companies & Skills Data USA

A high-performance Indeed scraper that extracts complete job listings from Indeed.com, the most-visited job portal in the United States with 350M+ monthly visits and 24M+ active postings across every industry — IT, healthcare, finance, manufacturing, retail, hospitality and the public sector. Pull 30+ structured fields per job in seconds, with salary automatically parsed to numbers, remote flag detected, posting date normalized to ISO 8601, plus full job description from the schema.org JobPosting block when fetchDetails is enabled.

Built for recruiters tracking talent supply, market analysts comparing US labor demand against portals like LinkedIn Jobs and Glassdoor, compensation consultants enriching benchmarks across BLS data, founders monitoring competitor hiring, and ML teams training resume-to-job matching models. Output is clean JSON suitable for direct ingestion into Google BigQuery, Snowflake, Postgres, or Google Sheets.

What this Indeed scraper does

This actor automates browsing indeed.com the way a real visitor does. It hits the public job search pages, walks through pagination, parses Indeed's internal mosaic-provider-jobcards JSON blob embedded in the HTML, and (optionally) opens each job's detail page to extract the full description plus the structured schema.org JobPosting baseSalary, hiringOrganization, validThrough, and jobLocation fields.

The pricing logic is automatic: a salary string like "$55,000 - $179,400 a year" becomes salaryMin: 55000, salaryMax: 179400, salaryType: "YEARLY", salaryCurrency: "USD". Hourly rates like "$44 - $54 an hour" are kept as hourly and labeled accordingly so downstream code can annualize fairly.

The scraper is HTTP-only (no headless browser) and uses TLS-fingerprint impersonation to look like a real Chrome session. It runs on Apify's residential proxy network out of the box, so you don't need to manage your own proxy pool. Memory footprint is tiny — 512 MB — making it 10× cheaper than browser-based competitors that rent 4 GB instances for the same job.

Data fields the Indeed scraper extracts

Every record contains these fields when present in the data:

  • jobkey — Indeed's unique job identifier
  • title — Position title
  • displayTitle — Title as styled on Indeed
  • normalizedTitle — Indeed's internal normalized title
  • jobUrl — Direct redirect link to the listing
  • applyUrl — Third-party application URL when present

Company

  • companyName — Hiring company
  • companyRating — Indeed's rating out of 5 when known
  • companyReviewCount — Total employee reviews on Indeed
  • companyReviewLink — Indeed company reviews page
  • companyOverviewLink — Indeed company profile page
  • companyLogoUrl — Logo URL (when fetchDetails=true)
  • companySameAs — External company URL from JSON-LD (when fetchDetails=true)

Location

  • formattedLocation — Display string ("Strongsville, OH 44136")
  • jobLocationCity — Parsed city
  • jobLocationState — US state code or province
  • addressLocality, addressRegion, addressCountry, postalCode — Full address (when fetchDetails=true)
  • remote — Boolean: is this a remote job?

Salary

  • salaryText — Raw display string ("$55,000 - $179,400 a year")
  • salaryMin — Lower bound number
  • salaryMax — Upper bound number
  • salaryTypeYEARLY / HOURLY / MONTHLY / WEEKLY
  • salaryCurrency — Currency code (typically "USD")
  • salarySource — Source label: EXTRACTION vs employer-stated
  • Optional duplicate fields from JSON-LD: salaryMinLd, salaryMaxLd, salaryUnitLd, salaryCurrencyLd, salaryValueLd

Snippet & description

  • snippet — Clean text preview of the job posting (search result excerpt)
  • snippetHtml — Original HTML preview
  • jobDescription — Full description text (only with fetchDetails=true)
  • jobDescriptionHtml — Original HTML markup (only with fetchDetails=true)

Timing

  • postedRelative — "30+ days ago", "22 days ago", "Just posted"
  • postedDate — ISO 8601 timestamp derived from Indeed's pubDate
  • createdDate — Original creation timestamp when Indeed exposes it
  • datePosted — ISO 8601 from JSON-LD (when fetchDetails=true)
  • validThrough — Expiration date from JSON-LD when employer set it

Posting flags

  • sponsored — Paid placement?
  • urgentlyHiring — Highlighted urgent listing?
  • newJob — Marked as new by Indeed?
  • expired — Closed posting?
  • featuredEmployer — Premium employer status
  • isTopRatedEmployer — Top-rated badge from Indeed
  • indeedApplyEnabled — Can apply via Indeed?
  • directApply — Direct apply enabled (JSON-LD)
  • openInterviewsJob — Indeed "Open Interviews" tagged

Job type & taxonomy

  • jobTypes — Array of types ("Full-time", "Contract", "Part-time", "Internship")
  • employmentType — Normalized employment type (JSON-LD)
  • industry — Industry classification (JSON-LD)
  • skills — Array of skill tags from Indeed's taxonomy

Benefits

  • benefits — Array of ranked benefits ("Health insurance", "401(k)", etc.)

Use cases for this Indeed data API

  1. Recruitment talent radar — Build a daily-refreshing stream of new listings matching your hiring niche. Filter by remote, salaryMin, and urgentlyHiring to surface the most actionable opportunities.
  2. US compensation benchmarking — Aggregate salaryMin/salaryMax by city + role to produce reliable pay bands. The salaryType field lets you cleanly separate hourly vs annual data.
  3. Hiring intelligence — Track which companies are scaling specific functions (e.g. AI/ML engineers, growth marketers, sales). Combine companyName with the industry field for clean segmentation.
  4. Resume-to-job ML training corpora — Pair title, jobDescription, skills, and salary fields to train recommendation or matching models against fresh real-world data.
  5. Lead generation for B2B services — Cold outreach to companies actively hiring in your niche (e.g. all USA companies hiring a "VP of Engineering"). Use companyName + jobLocationCity to build geographic outreach lists.
  6. Skill demand tracking — Weekly cron over the same keyword set, count skills occurrences over time. Detect emerging technologies and tooling before they hit industry reports.

How to use this Indeed scraper

You can drive the scraper in two ways: keywords mode (easiest — give one or many search keywords and a location) or urls mode (advanced — paste already-filtered Indeed search URLs).

Mode 1 — Search by keywords

{
"mode": "keywords",
"keywords": ["python developer", "data engineer"],
"location": "United States",
"country": "us",
"maxJobs": 100,
"fetchDetails": false
}

Mode 2 — Filtered search by city + remote-only + salary floor

{
"mode": "keywords",
"keywords": ["software engineer"],
"location": "Austin, TX",
"country": "us",
"maxJobs": 200,
"remoteOnly": true,
"salaryMinUsd": 120000,
"fetchDetails": true
}

Mode 3 — Search by URLs

{
"mode": "urls",
"searchUrls": [
{ "url": "https://www.indeed.com/jobs?q=devops+engineer&l=San+Francisco%2C+CA&sc=0kf%3Aattr%28DSQF7%29%3B" }
],
"maxJobs": 50,
"fetchDetails": true
}

Input parameters

ParameterTypeDefaultDescription
modeenum"keywords""keywords" or "urls"
keywordsarray["python developer"]Search keywords
locationstring"United States"US location filter
countryenum"us"Indeed subdomain: us, uk, ca, in, au
searchUrlsarray[]Pre-built search URLs (urls mode)
maxJobsinteger50Cap per keyword/URL (1–5000)
fetchDetailsbooleanfalseOpen each detail page for full description + JSON-LD
remoteOnlybooleanfalseKeep only remote-tagged jobs
salaryMinUsdinteger0Filter jobs by salary floor (hourly auto-annualized)
proxyConfigurationobjectRESIDENTIALApify proxy. Residential recommended for Indeed

Output example (single record, JSON)

{
"jobkey": "36f2876acf50d7da",
"title": "Software Engineer Lead/Experienced Python Developer",
"companyName": "PNC Financial Services Group",
"companyRating": null,
"companyReviewCount": null,
"formattedLocation": "Strongsville, OH 44136",
"jobLocationCity": "Strongsville",
"jobLocationState": "OH",
"remote": false,
"salaryText": "$55,000 - $179,400 a year",
"salaryMin": 55000,
"salaryMax": 179400,
"salaryType": "YEARLY",
"salaryCurrency": "USD",
"salarySource": "EXTRACTION",
"snippet": "We are seeking a highly experienced Python Developer for the Corporate Functions Technology team...",
"postedRelative": "30+ days ago",
"postedDate": "2026-04-22T00:00:00+00:00",
"sponsored": false,
"urgentlyHiring": false,
"newJob": false,
"expired": false,
"indeedApplyEnabled": false,
"jobTypes": ["Full-time"],
"benefits": ["Health insurance", "401(k)", "Paid time off"],
"skills": ["Python", "PySpark", "REST API"],
"jobUrl": "https://www.indeed.com/rc/clk?jk=36f2876acf50d7da&...",
"applyUrl": null
}

How to call this Indeed scraper from your code

From the Apify API (curl)

curl -X POST "https://api.apify.com/v2/acts/makework36~indeed-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mode": "keywords",
"keywords": ["data engineer"],
"location": "New York, NY",
"maxJobs": 100,
"fetchDetails": false
}'

From Python (apify-client)

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("makework36/indeed-scraper").call(run_input={
"mode": "keywords",
"keywords": ["python developer", "rust developer"],
"location": "United States",
"maxJobs": 200,
"fetchDetails": True,
"remoteOnly": True,
"salaryMinUsd": 100000,
})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
print(job["title"], job["companyName"], job["salaryMin"], job["salaryMax"])

From Node.js (apify-client)

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('makework36/indeed-scraper').call({
mode: 'keywords',
keywords: ['software engineer'],
location: 'Seattle, WA',
maxJobs: 100,
fetchDetails: false,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} jobs`);

Export to CSV

curl "https://api.apify.com/v2/acts/makework36~indeed-scraper/runs/last/dataset/items?format=csv&token=$APIFY_TOKEN" \
-o indeed_jobs.csv

Performance & cost

The scraper is fully HTTP — no headless browser. Memory footprint is 512 MB, dramatically lower than the 4 GB needed by browser-based competitors.

ModeTime per page (≈24 jobs)Time per detail100 jobs ETA
Search only (fast)~1–2 s~10 s
With fetchDetails=true~1–2 s + ~3 s/job~3 s~3–4 min

For 1,000 jobs in search-only mode, expect 6–8 minutes including proxy rotation overhead. Detailed runs are slower but still 5× faster than browser scrapers.

Indeed scraper comparison

FeatureThis actorBrowser-based with proxyHeadless w/ captcha solver
Output fields30+ structured20–2520
Salary parsed (Min/Max/Type)partial
Hourly vs Yearly auto-detected
Memory footprint512 MB4 GB4 GB
Pure HTTP (no browser)
Captcha solver required
Pricing modelPAY_PER_EVENT tieredflat or rentalflat

Step-by-step tutorial — your first run in 2 minutes

  1. Click Try for free at the top of this page.
  2. In the input form, leave mode as keywords and country as us.
  3. Replace the default keyword (e.g. "software engineer") and set location to your target city.
  4. Set maxJobs to 20 for a quick first run.
  5. Leave fetchDetails off — keeps the run fast.
  6. Click Start. The run finishes in 10–20 seconds.
  7. Open the dataset tab; you'll see a table with titles, companies, locations, salaries.
  8. Export as CSV, JSON or Excel from the Export button.
  9. Once happy with the output, increase maxJobs, enable fetchDetails, or schedule a recurring run.

Advanced usage patterns

Pattern A — Daily talent radar by ZIP code

Schedule the actor daily with location: "94103" (or any 5-digit US ZIP). You get all new jobs in that ZIP delivered as a CSV each morning.

Pattern B — Multi-state compensation atlas

Loop over keywords and US states. Aggregate salaryMin/salaryMax grouped by state and salaryType. Visualize as a US heatmap of pay bands.

Pattern C — Skill demand tracker

Weekly cron over 5 broad role categories. Count skills array elements across runs. Plot top-rising and top-falling skills over time.

Pattern D — Remote-only feed for global candidates

Set remoteOnly: true + salaryMinUsd: 80000. Only the highest-quality remote jobs reach your dataset. Combine with email integration for daily delivery.

Pattern E — Competitor hiring tracker

Use keywords matching specific competitor names or roles they typically post. Track frequency of new postings; correlated to their growth phases.

Troubleshooting

Some salary fields are null. About 30–40% of Indeed postings don't list salary in the search results. Enabling fetchDetails: true recovers salary on a portion of these via the JSON-LD baseSalary field, but employers who don't disclose at all will remain null.

The actor only returns ~24 jobs even though I asked for 200. Indeed paginates in steps of 10 (sometimes 24 per page in the desktop layout). If your query is rare, total results might genuinely be small. Check the search on indeed.com directly to confirm the available pool.

HTTP 403 errors in the logs. This is normal — Indeed rate-limits each IP after 1–2 requests. The actor automatically rotates Apify residential proxy sessions and retries. As long as the final job count is non-zero, the scraper recovered.

My run hit the proxy budget limit. Each search page is ~1.8 MB. For 1,000 jobs (≈42 pages) expect ~75 MB of proxy traffic. Check your Apify account's residential proxy allowance, or set a tighter maxJobs value.

remoteOnly: true is filtering too aggressively. Indeed's remoteLocation flag is set conservatively. Some jobs that the description says are remote aren't tagged as remote in the data. Use fetchDetails: true and post-filter by searching for "remote" in jobDescription.

I want only specific job types (e.g. only Full-Time). Pre-filter using Indeed's URL filter (e.g. &jt=fulltime or &jt=contract) via mode: urls, or post-filter on the jobTypes array in the output.

Pricing

This actor uses PAY_PER_EVENT pricing with tiered volume discounts.

TierStandard job (search only)Detailed job (with fetchDetails)
FREE$3.00 / 1K$7.50 / 1K
BRONZE$2.20 / 1K$5.50 / 1K
SILVER$1.60 / 1K$4.00 / 1K
GOLD$1.10 / 1K$2.80 / 1K
PLATINUM$0.85 / 1K$2.20 / 1K
DIAMOND$0.60 / 1K$1.80 / 1K

Plus a one-time $0.001 per actor run. A typical 200-job standard run costs $0.60 (FREE) or as little as $0.12 (DIAMOND).

FAQ

Why is this Indeed scraper cheaper than other actors? It's pure HTTP — no browser, no GPU rendering, no XVFB. That's a 10× memory saving versus browser-based competitors, which the pricing passes back to you.

Is scraping Indeed.com legal? This actor accesses publicly available search and listing pages — no login, no paywall bypass, no PII extraction beyond what employers post publicly. Always check Indeed's terms of service and consult counsel for your jurisdiction.

How fresh is the data? The scraper fetches in real time when you start a run. Indeed updates listings continuously throughout the day. Schedule the actor as often as your use case demands.

Can I scrape Indeed without writing code? Yes — use the input form on this page, click Start, then download the dataset as CSV or Excel. No Python or Node required.

Does this support Indeed Canada / UK / Australia / India? Yes. Set country to ca, uk, au, or in and the scraper hits the matching Indeed subdomain (ca.indeed.com, uk.indeed.com, etc.).

Why does the actor need Residential proxies? Indeed blocks datacenter IPs aggressively. Residential proxies have IP addresses from real households, which Indeed accepts. Apify includes residential proxy access in most paid plans.

What if Indeed changes its data format? The scraper uses defensive parsing with both the embedded mosaic-provider-jobcards blob and the schema.org JobPosting JSON-LD on detail pages. When Indeed changes one, the other usually still works. Fixes typically land within 24–48 hours.

Does the scraper deduplicate jobs? Yes. Each jobkey is unique; the scraper tracks seen keys across pages and won't push duplicates.

Is there a rate limit? The actor inserts a small jitter between pages and rotates proxy sessions automatically. For very large runs (>5,000 jobs) consider splitting across multiple Apify Tasks scheduled minutes apart.

Can I scrape jobs from a specific company on Indeed? Yes — use mode: urls and pass an Indeed company jobs URL (e.g. https://www.indeed.com/cmp/Google/jobs). The scraper treats it like any search page.

Changelog

  • 0.1 (2026-05) — Initial release. Keywords + URLs modes. Search + detail JSON-LD. 30+ fields. Residential proxy default.

This Indeed scraper accesses publicly available information. It does not bypass authentication, paywalls, or extract personally identifiable information beyond what employers and Indeed display publicly. Users are responsible for complying with Indeed's terms of service, the Computer Fraud and Abuse Act, and any data protection regulations applicable in their jurisdiction (e.g. CCPA, GDPR if scraping EU jobs). The author of this actor accepts no responsibility for misuse.