Blog/Sales & enrichment
5 min read

Indeed Job Search API: Pull Jobs by Role and City as Data

Search Indeed jobs by role, city and recency from your agent, see what a job record carries, and what a city search really returns. Billed per call.

Indeed Job Search API: Pull Jobs by Role and City as Data

Get the jobs for a role in a city as rows, from your agent. Paste this into your agent:

Set up https://monid.ai/SKILL.md, and then use Monid to search Indeed for data engineer jobs in Austin, TX posted in the last 7 days with staffing agencies excluded, and give me a table with title, company, location, salary and link.

One prompt runs a whole job search. 1 min setup · 20-40 hrs saved.

You want the jobs for a role in a city as data: for a job-market tracker, a newsletter of fresh openings, a salary sample or a lead list of companies that are hiring. This guide shows how to run that search from an agent, what a job record carries (we ran a live job search on 2026-10-16), and what a "jobs in Austin" search really returns. It runs through Monid, the OpenRouter for agent tools: one key, one balance, every tool priced per call.

What is the easiest way to get Indeed job search data through an API?

Monid. Install it once, add a key, and your agent calls Indeed job search, job details and company endpoints with no portal, no plan and no partner application on your side.

  • Pay per call. Each call is billed on its own: $0.10 for an Indeed job search and $0.02 for the full record of one posting (Verified 2026-10-16 on the jobs tools page). Buy calls as you need them: no monthly plan and no minimum top-up. Discovery and inspection are free; only a run bills.
  • One install, every job source. The same key and balance also call Google Jobs and Wellfound endpoints, so a second job board is a changed -p flag, not a new account.
  • Lives inside your agent. Install the CLI, add your key, paste the prompt above, and the tools are there whenever your agent needs them, on demand, with nothing to keep running. Your agent reads SKILL.md and learns the rest, so setup is about a minute.

At that price a hundred Indeed searches cost $10.00 (Verified 2026-10-16). That is the number to plan around, and the reason the later sections show a cheaper way to run the first sweep.

How do you search Indeed jobs by role and city?

Run one search call with a role, a place and a recency window, then page with start. The search endpoint takes query (the only required field), location, fromage, jt, explvl, start, exclude_staffing_agencies and exclude_companies. If you want one company's open roles instead of a market search, job postings as hiring signals covers that call.

For agents

Grab an API key at app.monid.ai, then paste this to your agent and hand it the key:

set up https://monid.ai/SKILL.md

It learns the whole discover, inspect, run workflow itself. More in the agent quickstart.

For humans

npm install -g @monid-ai/cli
monid keys add -k <your-api-key> -l main

The call

monid run -p indeed -e /search_jobs \
  --query '{"query":"data engineer","location":"Austin, TX","fromage":"7","exclude_staffing_agencies":true}'

fromage is the maximum age in days and takes 1, 3, 7, 14 or 30. location accepts a city and state, a ZIP, or the literal remote. jt takes fulltime, parttime, contract, internship or temporary, explvl takes entry_level, mid_level or senior_level, and start pages in steps of ten. exclude_staffing_agencies is a true or false switch, and exclude_companies takes a comma-separated list of exact company names. The endpoint's own description calls the staffing filter a keyword and name heuristic, so smaller agencies can still appear.

This endpoint returns the search page as Indeed renders it, not a flat jobs array, and its listed median run time is about 122 seconds (Verified 2026-10-16 from monid inspect). Plan for a slow call, not a quick lookup.

A second Indeed route takes a JSON body and returns normalized rows, up to 20 per request. It bills a flat $0.00088 plus $0.00009 per result returned, so a lower limit costs less (Verified 2026-10-16):

monid run -p anyapi -e /indeed.jobs \
  -i '{"query":"data engineer","location":"Austin, TX","postedLimit":"week","limit":20}'

Its documented fields include title, company, city, state, salaryMin, salaryMax, salaryUnit, datePublished, description, applyUrl and jobId. We inspected this endpoint and did not run it, because a per-result price with a flat fee can bill more than a single listed number suggests.

Or hand the whole job to an agent

Give this to your agent

$Set up https://monid.ai/SKILL.md, and then use Monid to search for data engineer jobs in Austin, TX posted in the last 7 days, exclude staffing agencies, and give me one table with title, company, location, salary and link, sorted by newest first.

Can you scrape Indeed yourself with Python?

Yes, people do it with Requests, BeautifulSoup, Selenium or Playwright, and it works until the page changes or the site starts blocking you. A scraper you write is yours to keep alive: when the markup, the blocking or the rate limits change, your job breaks, and your list of fresh jobs is only as fresh as your last successful run.

The rules side differs by site and by country. Read the terms of any job board before you build a pipeline on its pages, and check the rules that apply to you and to the people named in the data.

Doing it in Python means a proxy or browser setup, parsing code, retries, paging and a repair every time the page changes. That is hours before the first useful row and a standing maintenance job after it. Through Monid the collection is maintained for you and the output is JSON instead of HTML you parse, billed per call. For anything you will run more than once, the hours go into upkeep, and job scraping software, board by board shows why one board's scraper does not cover the rest. A downloadable Indeed dataset is quicker for a one-off look, but it is a snapshot of one date for the searches its author chose.

What does a job search record contain, and what can you build with it?

A search record is a short card, and the full description sits one call behind it. We ran a Google Jobs search on 2026-10-16 for "data engineer" in Austin, Texas, so the fields below are what came back, not what a spec promises.

The search row

One call returned 10 rows. Each row carried these fields, trimmed:

{ "rank_absolute": 4,
  "job_id": "oKspHKF6ndCKUdNKAAAAAA==",
  "title": "Junior Data Engineer",
  "employer_name": "BeaconFire Inc.",
  "location": "United States",
  "source_name": "via LinkedIn",
  "source_url": "https://www.linkedin.com/jobs/view/…",
  "salary": "62K to 80K a year",
  "contract_type": "Full-time",
  "timestamp": "2026-10-16 04:56:10 +00:00",
  "time_ago": "1 day ago" }

The row also carries employer_image_url, employer_url, position, rank_group and xpath. employer_url was null on all 10 rows, so a search row gives you the company name and a logo, not its website. The post age comes as both a timestamp and a time_ago string, and the Meta row had neither.

The Indeed card and the full record

The Indeed search endpoint describes its response as job cards with titles, companies, locations and salary snippets, plus pagination links. The detail endpoint takes a 16-character job key from those results and returns the description, salary data, posting age, candidate count, company info, benefits and application links, according to its monid inspect text. We inspected both and did not run them, at $0.10 and $0.02 a call (Verified 2026-10-16).

What you can build with it

  • A fresh-openings feed. Run the same role and city every morning with fromage set to 1, and send the rows you have not seen before. The ids make the "have I seen it" check one line.
  • A salary sample for a role. Collect the rows that carry a pay range and compute a median; salary data from three sources shows how the ranges differ between sources.
  • A list of hiring companies. Group rows by employer and rank by number of open roles; If LinkedIn is your second source, the best LinkedIn scraper APIs of 2026 compares the options.

What goes wrong when you search jobs by city?

Four things hide until you read the rows instead of the count. All four came out of the single Austin run on 2026-10-16.

Why does a search for Austin return jobs outside Austin?

Because a city in a job search is a pull, not a boundary. Of the 10 rows, 1 was in Austin:

Austin, TX 1    Plano 1    Houston 2    Dallas 1
United States 1    Remote, OR 1    Menlo Park (+2 others) 1
Anywhere 1    Boulder (+1 other) 1

Four more were in Texas, and the rest were remote, national or in other states. Filter on location after you pull, and treat a row with "(+2 others)" as several places, not one. If you count jobs per city from the raw rows you will overstate the city.

Does the same job show up on more than one board?

Yes, and the row tells you which board it came from. source_name read "via LinkedIn" on 3 rows, "via BeBee" on 2, and one each for Dice, Motion Recruitment, Meta Careers, Jobright and Clearance Jobs. None read "via Indeed". The same role can appear again under another source when you merge several searches. Key your store on a normalized title plus employer plus location, not on one board's id, and keep source_name as a column so you can see where each copy came from.

How fresh are the rows?

Fresher than a dataset, older than you expect. 5 of the 10 rows were three days old or less, 4 were older than a week (8, 12, 14 and 16 days), and the Meta row carried no date. If your feed is meant to be "this week", filter on timestamp yourself or set the recency window on the way in: Indeed takes fromage, the second Indeed route takes postedLimit.

What did the call cost?

The listed price of the Google Jobs search is $0.0012 a page of 10 results (Verified 2026-10-16). The run we made returned one page of 10 rows, reported 1 billed unit and was charged $0.0024. That is twice the listed figure, and the run was a single page, so it was not a second page. Budget at twice the listed price until your own receipt says otherwise, and read the cost field on the first run rather than the price on the tool page. At $0.0024 a page, a hundred pages of 10 jobs is $0.24.

Which endpoint should I use for which job?

EndpointWhat it doesInputReturnsLatencyBilling
indeed/search_jobsSearch Indeed by role, place, recencyquery, location, fromage, jt, explvlThe search page with job cardsMedian about 122 sPer call
indeed/get_job_detailsOne posting in fulljk, a job key from searchDescription, salary, company info, apply linksMedian about 122 sPer call
anyapi/indeed.jobsIndeed search as normalized rowsquery, location, postedLimit, limitUp to 20 rows with pay and descriptionAbout 3.7 s median listedFlat fee plus per result
dataforseo/serp/google-jobsJobs from many boards, as Google lists themkeyword, location_name, depth10 rows per page with source, pay, ageAbout 12 s measuredPer page of 10
wellfound/search_jobsStartup jobs by role and placeRole and locationJobs with startup detailsAbout 4 s median listedPer call

Every row was inspected with monid inspect on 2026-10-16. Only the Google Jobs row was run, which is why its latency is the one we measured. The other latencies are the medians listed on the tool page. Billing shape is given here, and the current figures are on monid.ai/tools.

The first two rows answer a question about one board. The Google Jobs row answers a question about the market: which jobs exist for this role, wherever they were posted. Use the market view first to find out which roles and employers matter, then spend the Indeed calls on the ones worth reading in full.

When is another route a better fit?

You need every job in a city, not a sample. A search page returns a page of results, not the market. If the answer must be complete, budget the pages first: ten results per page of the Google Jobs route, ten per start step on Indeed.

You need the description of every posting. The search row is a card. The description is a separate call per posting, so a feed that reads every body costs one search plus one detail call per row. Rank on the card, then fetch details only for the rows that survive.

You need speed. The Indeed search endpoint lists a median of about 122 seconds, which suits a nightly batch and not an interactive lookup. The Google Jobs route took about 12 seconds in our run.

You need a guaranteed city. As the Austin run showed, one city search brings back other cities and remote roles. If the boundary matters, filter after the pull.

And the disclosure: we resell these endpoints. The most useful thing in this post is that you should filter the city after the pull and read the receipt of the first run, which costs nothing and holds whoever you buy the data from.

Conclusion

The quickest way to get Indeed jobs for a role and a city is one search call through Monid: $0.10 a call (Verified 2026-10-16), one key for Indeed and every other job source, about a minute to set up and ready inside your agent whenever you need it. Scraping it yourself works until the page changes, and costs hours of setup; Monid keeps the collection maintained.

Two things matter more than the choice of endpoint. A city search is a pull: 1 of the 10 rows in our Austin run was in Austin, so filter on location after you pull. And read the receipt: the Google Jobs page we ran was listed at $0.0012 (Verified 2026-10-16) and charged $0.0024, so plan from the first run's cost, not the listed price.

How we estimated the time saved: building and maintaining an Indeed route and a second job source yourself is roughly 10 to 20 hours each for the setup, the parsing, paging and the first month of upkeep. That is 20 to 40 hours. The 1 minute is the install, key and first call once you already have a Monid key.

Free next step: run monid discover "job search", then monid inspect -p dataforseo -e /serp/google-jobs, make one call for your role and city, and count how many rows are in the city. Start at monid.ai.

FAQ

Does Indeed have an API, and how do you get an API key?

Whether a job board offers a search API to you depends on its partner programs, and those are decided by the board, not by this guide. The practical route is to use an endpoint that already exists: through Monid you install the CLI, add one Monid key, and call the Indeed search endpoint at $0.10 a call (Verified 2026-10-16). There is no separate Indeed key to apply for on your side.

Is there a free Indeed API?

Not free, but you pay only for what you run: there is no plan and no minimum, and discovery and inspection cost nothing. An Indeed search is $0.10 a call and one posting in full is $0.02 (Verified 2026-10-16). The cheapest way to look at the market is the Google Jobs route at a listed $0.0012 a page of 10 rows, which billed $0.0024 in our run.

How do you get the full job description, not just the card?

Take the job key from a search result and call the detail endpoint. It returns the description, salary data, posting age, candidate count, company info, benefits and application links. It is a separate call per posting, so rank on the card first and fetch details only for the postings you keep.

How many jobs can one search return?

One page. The Indeed search pages in steps of ten with start, the second Indeed route returns up to 20 rows per request, and the Google Jobs route returns 10 per page, up to 200 in total with depth. Our Google Jobs run returned exactly 10 rows. Loop over pages and role-and-city pairs for more.

Can you export Indeed jobs to a CSV?

Yes, once you have the rows as JSON. Run the search, keep title, the employer, location, the pay range and the link, and write them to a CSV with whatever tool you like, or ask your agent to do it in the same prompt.

Published October 2026.

indeed apiindeed job search apijob search apiindeed scraperjob listings data