Indeed Jobs API
An Indeed jobs API that returns live listings as flat JSON, one row per job, with no Indeed partner key. Search by keyword and location on any of 62 Indeed country sites and filter by job type, remote or hybrid, experience level, date posted, Easy Apply, radius and a yearly pay floor. Or pass Indeed search-results URLs with their filters intact, single job URLs, or a company's jobs page to list every open role there. Each row carries the pay range parsed into minimum, maximum, period and currency, with a flag for when the figure is Indeed's estimate rather than the employer's, plus benefits, the apply link, the sponsored and urgently hiring flags, and the full description as Markdown, plain text or HTML. Employer industry, size, revenue and headquarters are an optional add-on billed once per company. You pay per job returned, and rows that explain a failed input are free.
Input parameters
| PARAMETER | TYPE | REQ | DEFAULT | DESCRIPTION |
|---|---|---|---|---|
| mode | enum | yes | search | What to run: search (keywords, a location and filters), url (job posting or search-results URLs you already hold) or company (every job on an Indeed company jobs page). |
| keywords | string[] | no | — | Job titles or keywords, each searched separately and in parallel, up to 5 per run. Indeed's own syntax works: quotes for a phrase, a leading minus to exclude a word, title:(...) to match titles only. Search mode. |
| location | string | no | — | A city, region, zip code or Remote, for example Austin, TX. Empty searches the whole country. Search mode. |
| country | string | no | US | Two-letter code of the Indeed country site to read, for example US, GB, CA, AU, IN, DE or FR. The matching host is picked automatically. |
| domain | string | no | — | Optional host override such as uk.indeed.com. Leave empty and the country code decides. |
| datePosted | enum | no | — | Only jobs posted within this window: Last 24 hours, Last 3 days, Last 7 days or Last 14 days. Empty means any time. Search mode. |
| jobType | string[] | no | — | Employment types: fulltime, parttime, contract, temporary, internship, permanent, new_grad or commission. Each type is searched separately for every keyword. Search mode. |
| remote | enum | no | any | Work arrangement: any, remote or hybrid. Search mode. |
| experienceLevel | enum | no | — | Only roles Indeed classifies as entry, mid or senior. Empty means any level. Search mode. |
| sortBy | enum | no | relevance | relevance for Indeed's best matches first, or date for the newest postings first. Search mode. |
| easyApplyOnly | boolean | no | false | Only postings that accept Indeed's one-click apply. Search mode. |
| minPay | integer | no | — | Yearly pay floor in the local currency. Hourly, daily, weekly and monthly pay is converted to a yearly figure first, and jobs that state no pay are left out when a floor is set. Search mode. |
| locationRadiusMiles | integer | no | — | Search radius around the location: 0, 5, 10, 15, 25, 35, 50 or 100 miles. Other values snap to the nearest. Search mode. |
| jobUrls | string[] | no | — | Indeed job posting URLs (one job each) or search-results URLs (filters kept), up to 100 per run. Country sites such as fr.indeed.com work. URL mode. |
| companyJobUrls | string[] | no | — | Indeed company jobs pages such as https://www.indeed.com/cmp/ |
| maxResultsPerInput | integer | no | 50 | Most jobs to return for each keyword, search URL or company page, 1 to 1,000. Single job URLs return one job each. — drives your bill |
| uniqueJobsOnly | boolean | no | true | Return and bill each job once per run, even when several keywords or URLs find it. |
| includeCompanyDetails | boolean | no | false | Add the employer's industry, size, revenue, headquarters and profile text to each job. Billed once per distinct employer on top of the per-job fee. — drives your bill |
| descriptionFormat | enum | no | markdown | markdown keeps headings and bullet lists, text strips formatting, html is the original, all returns the three on the same row. |
Output schema
| FIELD | TYPE | DESCRIPTION | NULLABLE |
|---|---|---|---|
| result_type | string | Row kind: job for a billed job row, or error for a free row that explains why an input returned nothing. | no |
| jobId | string | Indeed's job key, the jk value in a viewjob URL, stable for the life of the posting. The dedupe key within a run. | yes |
| jobTitle | string | The job title as posted. | yes |
| companyName | string | The hiring company's name. | yes |
| companyUrl | string | The employer's Indeed company page. | yes |
| companyWebsite | string | The employer's own website, when the posting or company details list one. | yes |
| companyRating | number | Employer rating out of 5, when rated. | yes |
| companyReviewsCount | integer | Number of employee reviews behind that rating. | yes |
| companyLogo | string | Company logo image URL. | yes |
| companyIndustry | string | Employer's industry. Company details add-on. | yes |
| companySize | string | Employer's headcount band. Company details add-on. | yes |
| companyRevenue | string | Employer's revenue band. Company details add-on. | yes |
| companyHeadquarters | string | Employer's headquarters location. Company details add-on. | yes |
| companyDescription | string | Employer's own profile text. Company details add-on. | yes |
| companyDetailsAdded | boolean | True when the company details add-on filled this row. | yes |
| location | string | Location as shown on the listing. | yes |
| jobLocation | string | Fuller location string, with the street address when the listing gives one. | yes |
| city | string | City of the job. | yes |
| state | string | State or region code. | yes |
| postalCode | string | Postal code, when the listing gives one. | yes |
| region | string | State or region code, the same value as state. | yes |
| country | string | Two-letter country code of the Indeed site. | yes |
| domain | string | The Indeed host the listing came from. | yes |
| isRemote | boolean | True when the listing is marked remote. | yes |
| workModel | string | Work arrangement as labelled, for example Remote or Hybrid work. | yes |
| jobUrl | string | Canonical Indeed URL for the posting. | yes |
| applyUrl | string | Direct apply link, when the posting exposes one. | yes |
| datePosted | string | Posting date as an ISO 8601 timestamp. | yes |
| datePostedText | string | Posting age as Indeed shows it, for example 30+ days ago. | yes |
| jobType | string | Employment type, for example Full-time. Several types are joined with a comma. | yes |
| salaryText | string | Pay exactly as written on the listing. | yes |
| salaryMin | number | Lower bound of the pay range. | yes |
| salaryMax | number | Upper bound of the pay range. | yes |
| salaryPeriod | string | Pay period of the range: HOURLY, DAILY, WEEKLY, MONTHLY or YEARLY. | yes |
| salaryCurrency | string | Currency code of the pay range. | yes |
| salaryIsEstimated | boolean | True when the range is Indeed's estimate rather than the employer's own figure. | yes |
| benefits | array | Benefits listed on the posting. | yes |
| qualifications | array | Qualifications listed on the posting. | yes |
| shiftSchedule | array | Shift and schedule requirements, for example Weekends as needed. | yes |
| isExpired | boolean | True when the posting is no longer active. | yes |
| isSponsored | boolean | True when the listing is a paid placement. | yes |
| isEasyApply | boolean | True when the posting accepts Indeed's one-click apply. | yes |
| isUrgentlyHiring | boolean | True when the employer flagged the role as urgently hiring. | yes |
| isHiringMultiple | boolean | True when the employer is hiring more than one person for the role. | yes |
| isNew | boolean | True when Indeed marks the posting as new. | yes |
| isFeaturedEmployer | boolean | True when the employer is featured on the listing. | yes |
| sourceName | string | The job board or applicant tracking system the posting came from. | yes |
| descriptionMarkdown | string | Full description as Markdown with headings and lists kept. With descriptionFormat markdown (the default) or all. | yes |
| descriptionText | string | Full description as plain text. With descriptionFormat text or all. | yes |
| descriptionHtml | string | Full description as the original HTML. With descriptionFormat html or all. | yes |
| searchKeyword | string | The keyword that found this job, in search mode. | yes |
| searchLocation | string | The location that found this job, in search mode. | yes |
| sourceInput | string | The keyword or URL from your input that produced this row. | yes |
| summary | string | One plain-language line per job, for agents that read rows as prose. | yes |
| error_message | string | Why one input returned nothing, on error rows. Error rows are never billed. | yes |
Worked examples
{"mode": "search", "keywords": ["python developer"], "remote": "remote", "datePosted": "Last 7 days", "sortBy": "date", "maxResultsPerInput": 50}
{"mode": "search", "keywords": ["registered nurse"], "location": "Dallas, TX", "jobType": ["fulltime"], "minPay": 80000, "maxResultsPerInput": 100}
{"mode": "search", "keywords": ["data analyst"], "location": "London", "country": "GB", "maxResultsPerInput": 50}
{"mode": "company", "companyJobUrls": ["https://www.indeed.com/cmp/Semrush/jobs"], "includeCompanyDetails": true, "maxResultsPerInput": 100}
{"mode": "url", "jobUrls": ["https://www.indeed.com/jobs?q=nurse&l=Dallas%2C+TX"], "maxResultsPerInput": 50}
Coverage
Code
Search in one call
curl -X POST "https://api.apify.com/v2/acts/johnvc~indeed-jobs-api/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"mode": "search", "keywords": ["data engineer"], "location": "Austin, TX", "datePosted": "Last 7 days", "maxResultsPerInput": 50}'
Python
from apify_client import ApifyClient
client = ApifyClient("APIFY_TOKEN")
run = client.actor("johnvc/indeed-jobs-api").call(
run_input={"mode": "search", "keywords": ["data engineer"], "location": "Austin, TX", "datePosted": "Last 7 days", "maxResultsPerInput": 50}
)
for row in client.dataset(run.default_dataset_id).iterate_items():
if row.get("result_type") == "error":
print("skipped:", row.get("error_message"))
else:
print(row.get("jobTitle"), "|", row.get("companyName"), "|", row.get("salaryText"), "|", row.get("jobUrl"))
MCP
claude mcp add --transport http indeed-jobs-api \ "https://mcp.apify.com/?tools=actors,docs,johnvc/indeed-jobs-api"
Sample job row (synthetic)
{
"result_type": "job",
"jobId": "0a1b2c3d4e5f6789",
"jobTitle": "Senior Data Engineer",
"companyName": "Example Corp",
"companyUrl": "https://www.indeed.com/cmp/Example-Corp",
"companyRating": 4.1,
"companyReviewsCount": 120,
"location": "Austin, TX",
"city": "Austin",
"state": "TX",
"country": "US",
"domain": "www.indeed.com",
"isRemote": false,
"workModel": "Hybrid work",
"jobUrl": "https://www.indeed.com/viewjob?jk=0a1b2c3d4e5f6789",
"applyUrl": "https://www.indeed.com/applystart?jk=0a1b2c3d4e5f6789",
"datePosted": "2026-10-04T15:00:00.000Z",
"datePostedText": "6 days ago",
"jobType": "Full-time",
"salaryText": "$140,000 - $165,000 a year",
"salaryMin": 140000,
"salaryMax": 165000,
"salaryPeriod": "YEARLY",
"salaryCurrency": "USD",
"salaryIsEstimated": false,
"benefits": [
"401(k)",
"Health insurance",
"Paid time off"
],
"isSponsored": false,
"isEasyApply": true,
"isUrgentlyHiring": false,
"isHiringMultiple": false,
"isNew": true,
"descriptionMarkdown": "## About the role\n\nYou will build and run the batch pipelines behind our reporting.",
"searchKeyword": "data engineer",
"searchLocation": "Austin, TX",
"sourceInput": "data engineer",
"summary": "Senior Data Engineer at Example Corp in Austin, TX. Pay: $140,000 - $165,000 a year. Full-time. Posted 6 days ago."
}
What people use it for
- Salary benchmarking by city from parsed Indeed pay ranges
- Watching one employer's Indeed jobs page for new roles
- Measuring the remote and hybrid share of postings by role
- Sales prospecting on hiring signals
- Enriching hiring employers with industry, size and revenue
- Feeding an AI recruiting agent Markdown job descriptions
More sources for Hiring signals and talent intelligence, Lead sourcing and CRM enrichment, Grounding AI agents and MCP tools →