Indeed Jobs Scraper — Job Listings & Salary Data API (No Key)
Pricing
from $1.50 / 1,000 results
Indeed Jobs Scraper — Job Listings & Salary Data API (No Key)
Keyless job-listings API in the spirit of Indeed — no login, no Cloudflare walls. Aggregates thousands of fresh openings from public job-board APIs plus real Indeed postings from the public web archive. Filter by keyword, location, remote, type and salary. Export to JSON, CSV or Excel.
Pricing
from $1.50 / 1,000 results
Rating
0.0
(0)
Developer
Logiover
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Indeed Jobs Scraper — Job Listings, Salary & Company Data API (No API Key)
An Indeed jobs scraper and structured job-listings data API in a single Apify Actor. Pull thousands of fresh job postings — title, company, location, salary, remote flag, job type, tags and full description — and export job data to JSON, CSV or Excel for recruiting, lead generation, salary benchmarking and labour-market analytics. No API key, no login, no cookie, no Cloudflare walls.
🏆 How it works (read this first — it's the honest bit)
Indeed's own website is protected end-to-end by Cloudflare Turnstile and returns
403to any keyless, self-contained scraper. So this Actor does not hammer indeed.com live — that approach is blocked for everyone without a paid unblocker. Instead it delivers the same kind of data, keyless and ToS-clean, through two engines:
live(default) — aggregates fresh openings from four public job-board developer APIs (Arbeitnow, RemoteOK, Jobicy, Himalayas), normalizes them into one unified schema, de-duplicates across sources, and filters by your keyword / location / remote / type / salary. A single run easily returns 500 – 1,000+ jobs.indeedArchive— pulls real Indeed job postings from the public web archive (web.archive.org, which is not behind Indeed's Cloudflare), parsing theJobPostingJSON-LD and Indeed's own job-cards data out of archived snapshots.You get Indeed-style job data with zero API keys and zero blocked requests. This README never claims to live-scrape indeed.com — because nobody can do that keyless, and honesty beats a broken promise.
✨ What this Actor does / Key features
- 💼 Thousands of fresh jobs per run — the
liveengine paginates four keyless job feeds and aggregates them into one dataset. Empty input alone returns 500+ current openings. - 🧭 Filter like Indeed — by keyword (title / skill / role), location (city, region, country or
remote), remote-only, job type (full-time / part-time / contract / temporary / internship), date posted and minimum salary. - 💰 Real salary data —
salaryMin,salaryMax,salaryCurrencyandsalaryPeriodas real numbers, plus a human-readablesalaryText, wherever the source publishes pay. - 🏢 Company + logo —
company,companyLogo, and a clickableapplyUrl/jobUrlon every row. - 🌍 Location, split for you —
location, plus best-effortcity/state/country, and a booleanremoteflag. - 📝 Full descriptions — both
descriptionHtml(original markup) and a cleandescriptionText, plus a shortsnippetfor previews. - 🔀 Cross-source de-duplication — the same job posted on two boards is merged by title + company, so you don't pay for duplicates.
- 🗄️ Real Indeed archive mode — historical Indeed postings via the Wayback Machine, with automatic Cloudflare-challenge-page detection (empty/challenge captures are skipped, never saved as junk rows).
- 🗂️ 3 pre-built dataset views — Overview, Live jobs, Indeed archive — slice the data with zero post-processing.
- ⚡ Keyless & fast — pure HTTP (no browser, no OAuth). Every item carries
source,_modeandscrapedAt(ISO 8601).
The 2 engines (modes)
| Mode | What it returns |
|---|---|
live | Aggregated fresh job feed from Arbeitnow + RemoteOK + Jobicy + Himalayas, normalized, de-duped and filtered (highest volume, the default). |
indeedArchive | Real Indeed job postings parsed from public web-archive snapshots (JobPosting JSON-LD + Indeed job-cards), Indeed-branded historical data. |
👥 Who is it for
- Recruiters & staffing agencies building a live pipeline of open roles and hiring companies.
- Lead-generation teams who want a fresh list of companies that are hiring (a company that's hiring is a company that's spending).
- HR & compensation analysts benchmarking salaries by role, seniority and location.
- Job-board & aggregator builders who need a keyless upstream feed to seed or supplement their own listings.
- Data scientists & researchers studying the labour market, remote-work trends, skills demand or wage distributions.
🎯 Use cases
- Recruiting pipeline — pull every open "React developer" or "registered nurse" role and route them to your ATS.
- Sales prospecting — a company hiring 20 engineers is scaling; surface it before your competitors do.
- Salary benchmarking — aggregate
salaryMin/salaryMaxby title and seniority to set competitive bands. - Remote-work analytics — filter
remote:trueand chart the share of remote roles by category over time. - Skills-demand tracking — count how often a technology appears in
tags/titleweek over week. - Market monitoring — schedule the Actor daily and diff the results to catch new postings the moment they appear.
💡 Why use it (vs. fighting Cloudflare yourself)
- It actually returns data. Live Indeed 403s keyless scrapers; this Actor sidesteps that entirely and still gives you rich job rows.
- No API keys, no accounts, no cookies. Nothing to register, rotate or get suspended.
- Volume by design. Real pagination across four sources → hundreds to thousands of rows in one run.
- Clean, typed output. Numbers are numbers, booleans are booleans, dates are ISO 8601 — ready for BI tools and ML.
- De-duplicated. You don't pay twice for the same posting appearing on two boards.
- Honest and maintainable. Public developer APIs + the public web archive don't change their locks weekly the way an anti-bot vendor does.
📊 What data can you extract
Every row — regardless of source or mode — is normalized to this unified schema:
| Field | Type | Description |
|---|---|---|
jobId | string | Stable id (source slug / id, or Indeed job key in archive mode). |
title | string | Job title. |
company | string | Hiring company name. |
companyLogo | string | null | Company logo URL when available. |
location | string | null | Full location string. |
city | string | null | Parsed city (best effort). |
state | string | null | Parsed state / region code (best effort). |
country | string | null | Parsed country (best effort). |
remote | boolean | Whether the role is remote. |
salaryMin | number | null | Lower bound of advertised pay. |
salaryMax | number | null | Upper bound of advertised pay. |
salaryCurrency | string | null | Currency code (e.g. USD). |
salaryPeriod | string | null | year / month / hour etc. |
salaryText | string | null | Human-readable pay string. |
jobType | string[] | Employment type(s): full-time, contract, … |
tags | string[] | Skill / topic tags (source-dependent). |
categories | string[] | Industry / category labels. |
seniority | string | null | Seniority / experience level. |
industry | string | null | Primary industry. |
snippet | string | null | Short plain-text preview. |
descriptionText | string | null | Full description, plain text. |
descriptionHtml | string | null | Full description, original HTML. |
datePosted | string | null | ISO 8601 posting date. |
applyUrl | string | null | Direct application URL. |
jobUrl | string | null | Canonical posting URL. |
source | string | arbeitnow / remoteok / jobicy / himalayas / indeed-archive. |
_mode | string | live or indeedArchive. |
scrapedAt | string | ISO 8601 timestamp of the scrape. |
Real output example (live mode)
{"jobId": "1135188","title": "Senior Backend Developer (Go)","company": "AlixPartners","companyLogo": "https://…/logo.png","location": "United States","city": null,"state": null,"country": "United States","remote": true,"salaryMin": 120000,"salaryMax": 160000,"salaryCurrency": "USD","salaryPeriod": "year","salaryText": "$120,000 - $160,000","jobType": ["Full-Time"],"tags": ["golang", "backend", "engineer", "senior"],"categories": ["Software Development"],"seniority": "Senior","industry": "Software Development","snippet": "We are hiring a senior Go engineer to scale our data platform…","descriptionText": "We are hiring a senior Go engineer…","descriptionHtml": "<p>We are hiring a senior Go engineer…</p>","datePosted": "2026-07-22T08:00:18.000Z","applyUrl": "https://remoteok.com/remote-jobs/1135188","jobUrl": "https://remoteok.com/remote-jobs/1135188","source": "remoteok","_mode": "live","scrapedAt": "2026-07-23T09:15:04.000Z"}
🚀 How to use (3 steps)
- Leave everything empty and click Start for the broadest feed (500+ fresh jobs from all live sources) — or add a keyword and/or location to narrow it.
- (Optional) tune the filters — remote-only, job type, minimum salary, date posted, or restrict to a single
source. SwitchmodetoindeedArchivefor real Indeed postings from the web archive. - Run & export — download as JSON, CSV, Excel, HTML, RSS or JSON Lines, or pull results via the Apify API / MCP.
Option A — Apify Console (no code)
Open the Actor, fill the input form (or leave it empty), press Start, then use the Export button on the dataset.
Option B — API / CLI
Start a run and read the dataset via the Apify API (see API usage below), or run it from the Apify CLI.
📥 Input parameters
Every field is optional. Empty input returns a broad, useful feed.
| Field | Type | Default | Description |
|---|---|---|---|
mode | select | live | live (aggregate public feeds) or indeedArchive (Indeed from web archive). |
query | string | – | Keyword: job title, skill, technology or role. Matched against title, company, tags, description. |
location | string | – | City, region, country, or remote. |
remote | boolean | false | Keep only remote jobs. |
source | select | all | all (aggregate + dedupe) or a single board: arbeitnow / remoteok / jobicy / himalayas. |
jobType | select | – | full-time / part-time / contract / temporary / internship. |
datePosted | select | any | any / 1 / 3 / 7 / 14 days. |
salaryMin | integer | – | Minimum advertised salary (drops jobs with no salary when set). |
maxResults | integer | 500 | Upper bound; drives how deep each source paginates. |
Example — broad fresh feed (empty input)
{}
Example — remote developer jobs, decent pay
{"mode": "live","query": "developer","remote": true,"salaryMin": 90000,"maxResults": 600}
Example — full-time nursing jobs, aggregated
{"mode": "live","query": "nurse","jobType": "fulltime","maxResults": 500}
Example — real Indeed postings from the web archive
{"mode": "indeedArchive","query": "software developer","location": "New York","maxResults": 200}
📤 Output
Results stream to the Actor's default dataset, one row per job, in the unified schema above. Three ready-made views are included:
- Overview — the common columns across every source and mode.
- Live jobs — the full aggregated feed (best for
live). - Indeed archive — archived Indeed postings (best for
indeedArchive).
Export any view to JSON, CSV, Excel, HTML, RSS or JSON Lines from the Console, or via the API.
🧠 Tips for best results
- Empty input = maximum volume. Add filters only to narrow. Start broad, then tighten.
- Use
maxResultsto control cost and depth. Higher values paginate more pages per source. source: allde-duplicates — same job on two boards is merged. Pick a single source only if you specifically want that board.- Keyword matches broadly — it checks title, company, tags and description, so
pythonsurfaces "Python", "Django/Python", etc. locationacceptsremote— combine withremote:truefor a strict remote filter.salaryMindrops unpaid-listing rows — many postings omit salary; set this only when you truly need pay data.- The live sources skew tech / remote — for warehouse, nursing or retail roles you'll still get hits, but volume is highest for software, marketing, sales and operations.
indeedArchiveis historical by nature — snapshots reflect when Indeed pages were captured, not this second. Use it for Indeed-branded data and back-testing.- Schedule it — run daily and diff datasets to catch brand-new postings.
- Watch
datePosted— filter to the last 1–7 days for a "what's new" feed.
🔌 Integrations
Send results anywhere Apify integrates: Zapier, Make, n8n, Slack, Google Sheets/Drive, GitHub, Airbyte, webhooks, or your own backend. Push job rows straight into a CRM, ATS, spreadsheet or data warehouse. Trigger runs on a schedule and pipe new rows to Slack or email.
🛠️ API usage
Start a run and fetch the dataset with the Apify API. Replace <TOKEN> with your Apify token.
cURL
# Start a runcurl -s -X POST "https://api.apify.com/v2/acts/logiover~indeed-jobs-scraper/runs?token=<TOKEN>" \-H "Content-Type: application/json" \-d '{"query":"developer","remote":true,"maxResults":600}'# Fetch dataset items (after it finishes)curl -s "https://api.apify.com/v2/acts/logiover~indeed-jobs-scraper/runs/last/dataset/items?token=<TOKEN>&clean=true&format=json"
JavaScript (apify-client)
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<TOKEN>' });const run = await client.actor('logiover/indeed-jobs-scraper').call({query: 'developer',remote: true,maxResults: 600,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items.length, 'jobs');
Python (apify-client)
from apify_client import ApifyClientclient = ApifyClient("<TOKEN>")run = client.actor("logiover/indeed-jobs-scraper").call(run_input={"query": "developer","remote": True,"maxResults": 600,})items = client.dataset(run["defaultDatasetId"]).list_items().itemsprint(len(items), "jobs")
🤖 MCP / AI agents
This Actor is a clean jobs data tool for AI agents. Because it's keyless and returns structured JSON, you can wire it into an LLM agent (via the Apify MCP server or a direct API call) to answer questions like "find remote Python jobs paying over $100k" or "list companies hiring data engineers this week". Every field is typed, so the model can filter, rank and summarize without scraping HTML itself.
❓ FAQ
Does this scrape indeed.com live?
No — and neither can any keyless scraper. Indeed's site is behind Cloudflare Turnstile and returns 403 to unauthenticated bots. This Actor instead aggregates keyless public job-board APIs (live) and parses real Indeed postings from the public web archive (indeedArchive). You get Indeed-style job data with no API key and no blocked requests.
Is there an Indeed job data API without an API key?
Yes — this Actor is that, in effect. It exposes a clean, keyless job-listings API you call through Apify: send a keyword/location, get back structured jobs. No Indeed key, no OAuth, no login.
How do I scrape Indeed jobs into a CSV?
Run the Actor (empty input or with a keyword), then click Export → CSV on the dataset, or call the API with format=csv. You can export Indeed-style job data to CSV, Excel or JSON in one click.
Where does the salary data come from?
From the sources that publish it (RemoteOK, Jobicy and Himalayas expose pay ranges; Indeed archive snapshots carry baseSalary in JSON-LD). Salary is stored as real numbers in salaryMin / salaryMax with salaryCurrency and salaryPeriod. Set salaryMin to keep only paid listings.
How many jobs can I get per run?
Hundreds to thousands. The default live mode aggregates four sources with real pagination — an empty run returns 500+, and maxResults can push it into the thousands.
Why do I see source: remoteok / jobicy and not indeed?
In live mode the data comes from those keyless job boards, tagged honestly with their source. Switch to mode: indeedArchive to get rows tagged indeed-archive sourced from real archived Indeed pages.
Does indeedArchive always return data?
It returns real Indeed postings when reachable, non-challenge snapshots exist for your query. Some archived captures are themselves Cloudflare "Just a moment" pages — the Actor detects and skips those rather than saving junk. For guaranteed volume, use the default live engine.
Can I get only remote jobs?
Yes — set remote: true (and/or location: remote). The live sources are remote-friendly, so remote volume is high.
Can I filter by job title or skill?
Yes — query matches against title, company, tags and description, so a skill like kubernetes or a role like product manager both work.
Is the data fresh?
The live sources update continuously (hourly on several boards) and are ordered newest-first, so you get current openings. Use datePosted to keep only the last N days.
Can I run this on a schedule?
Yes — use Apify Schedules to run it daily/hourly and pipe new rows to Slack, Sheets, a webhook or your database.
What if a source is temporarily down?
Each source is fetched independently with retries; if one is unavailable the others still deliver, so the run still returns data.
⚖️ Is it legal?
This Actor uses public developer APIs (Arbeitnow, RemoteOK, Jobicy, Himalayas — all of which publish these endpoints for third-party use) and the public web archive (archive.org). It does not bypass Indeed's authentication or anti-bot systems, and it collects only publicly available job-posting information — no personal data beyond what employers publish in a listing, and no login-gated content. You are responsible for complying with each source's terms and with applicable data-protection law (e.g. GDPR) when you store or process the results. When in doubt, consult your legal team.
🔗 Related scrapers
Looking for more hiring & company data? Explore the rest of the logiover collection on Apify for company registries, lead-generation and business-data Actors that pair well with this jobs scraper.