Job Scraping Software: Pull Postings From Each Board
Job scraping software for Built In, Y Combinator and Google Jobs: what each board returns, where the fields disagree, and how to merge them into one table.

Pull the same job search from three boards and merge it in one prompt. Paste this into your agent:
Set up https://monid.ai/SKILL.md, and then use Monid to pull data engineer jobs in Austin from Built In and from Google Jobs, and engineering jobs from Y Combinator's Work at a Startup, then give me one table with the board, title, company, salary text and posted date.
One prompt turns three boards into one table. 1 min setup · 12-24 hrs saved.
You want job postings as rows: what is open for a role, in a city, on the boards that matter to you. Search results for job scraping software sell one tool as if there were one feed. In practice each board has its own fields, its own salary format and its own idea of a date, so the work is choosing the boards and lining the columns up. This guide covers how to pull each board, what three of them returned when we ran them on 2026-10-16, and the traps in merging them. It runs through Monid, the OpenRouter for agent tools: one key, one balance, every tool priced per call.
What is the easiest way to use job scraping software without running a scraper?
Monid. Install it once, add a key, and your agent calls one endpoint per board with a role and a city and gets typed JSON back, with no scraper to host and no board account to open.
- Pay per call. A Built In job search bills $0.01 a call and a Y Combinator job search $0.01 (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 board. The same key and balance call Built In, Y Combinator, Google Jobs and every other tool. Adding a board is another call.
- Lives inside your agent. Install the CLI, add your key, run the prompt above, and the tools are there whenever your agent needs them. Your agent reads
SKILL.mdand learns the rest, so setup is about a minute.
The three runs behind this post returned 60 rows and billed $0.0224 in total (Verified 2026-10-16).
How do you collect job postings from several boards?
Run one search per board, keep the board name on every row, and merge afterwards. Do not look for one endpoint that covers everything: each board holds its own listings, so you choose the two or three where your roles live.
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
Find out which boards are available
monid discover -q "job board aggregator search"
monid discover -q "linkedin job postings search"
Discovery never bills. The lead generation tools page lists the boards. On 2026-10-16 a "job search postings" query listed endpoints for Built In, Y Combinator, Wellfound, Indeed, Google Jobs, LinkedIn, Web3 Career and Idealist, each with its own price and its own status. Two of those were marked degraded that day and we left them out of this guide.
Pull Built In
monid run -p builtin -e /search_jobs -w --query '{"query": "data engineer"}'
Add location to narrow it to a city, work_type to filter by arrangement and page to move on:
monid run -p builtin -e /search_jobs -w --query '{"query": "data engineer", "location": "Austin"}'
That call returned 25 jobs on page 1 of 3 and billed $0.01 (Verified 2026-10-16).
Pull Y Combinator
monid run -p ycombinator -e /search_jobs -w --query '{"role": "product"}'
This board takes a role category, not a free-text query: software-engineer, designer, recruiting, science, product, operations, sales, marketing, legal or finance. The call returned 25 jobs and billed $0.01 (Verified 2026-10-16).
Pull Google Jobs
monid run -p dataforseo -e /serp/google-jobs -w -i '{"keyword": "data engineer", "location_name": "Austin,Texas,United States", "language_code": "en"}'
This one is a POST, so the body goes in -i, and the location has to be spelled exactly as Google lists it. The call took about 12 seconds, returned 10 rows, which is one page, and billed $0.0024 (Verified 2026-10-16).
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 pull data engineer jobs in Austin from Built In and Google Jobs, and engineering jobs from Y Combinator, keep a column for which board each row came from, and flag rows that look like the same role on two boards.Can you scrape job boards yourself with Python?
Yes, and for one board it is a fair afternoon project. Open source libraries such as JobSpy wrap several boards behind one interface, so you can get breadth quickly.
What you take on is the upkeep. Each board changes its markup and its blocking on its own schedule, so a scraper that worked last month returns nothing this month. A fetch that works from your laptop gets refused from a server, which is where the proxy question starts. Board terms and local rules differ, so read the terms of each board and check the rules where you operate.
Through Monid the parsing and the blocking are the endpoint's job. A Built In search is $0.01 for 25 typed rows (Verified 2026-10-16), and a board that changes its page is fixed on the catalogue side. The trade is that you get the boards in the catalogue, not any site you can think of. For a board that is not there, browser automation when the site has no API shows where to look next, and which kind of scraping tool you need sorts the options by who maintains the parser.
What does a posting look like on each board?
Three boards gave three different records. We ran Built In, Y Combinator and Google Jobs once each on 2026-10-16, so the fields below are what came back.
Built In
Eleven fields per row, and the salary and seniority are the board's own labels, not text you have to parse:
{ "id": "11351310",
"title": "Data Engineer III - Click Stream Data Products",
"url": "https://builtin.com/job/data-engineer-iii-click-stream-data-products/11351310",
"company": "Expedia Group",
"company_url": "https://builtin.com/company/expedia-group",
"company_logo": "…",
"work_type": "Hybrid",
"location": "Austin, TX, USA",
"salary": "146K-234K Annually",
"experience_level": "Senior level",
"posted": "Reposted 4 Days Ago" }
work_type came back as Hybrid, In-Office, "Remote or Hybrid" and "In-Office or Remote". Fifteen of the 25 rows carried a salary and ten were null. Three had no experience_level.
Y Combinator
Eleven fields again, but a different eleven: id, title, type, location, role_category, salary, company_name, company_slug, company_batch, company_description and job_url. The row names the startup, its batch (S24, W26) and what it does. It has no posted date at all, and role_category was null on all 25 rows. Salary is present on every row we got, as text.
Google Jobs
The richest record and the least stable: job_id, title, employer_name, location, source_name, source_url, salary, contract_type, timestamp and time_ago, plus page-position fields (rank_group, rank_absolute, position, xpath). employer_url was null on all 10 rows. Five of the ten carried a salary. source_name says where the posting was found: three rows came from BeBee, three from LinkedIn, and one each from Dice, Motion Recruitment, Clearance Jobs and Jobright.
What you can build with it
- A weekly shortlist for one role. Run the same Built In query every week and list the ids that are new.
- A startup hiring map. Pull the Y Combinator roles for sales or engineering and group by
company_batchto see which cohorts are hiring. For hiring as a buying signal, see job postings API: hiring signals covers the sales side. - A salary spread by board. Parse the salary text from each board into a low and a high and compare what the same role pays on a startup board against a general one, as salary data from three sources does for pay data.
What goes wrong when you merge job boards?
Five things showed up in the three runs.
Why are the salaries not comparable?
Because every board writes them differently and none of them gives a number you can sort. These are the formats we saw:
# strings as returned, Verified 2026-10-16
Built In 146K-234K Annually
Y Combinator $140K - $207K | $140K | $130 - $195 | £90K - £130K GBP
Google Jobs a range with an en dash then "a year", or 91,225 to 172,200 a year
The Y Combinator row with a range of 130 to 195 has no K, so a parser that assumes thousands will get it wrong by a factor of a thousand. One row used pounds. Write one parser per board, keep the original string next to the parsed range, and store the currency.
Why is the posted date not a date?
Built In gives words ("Yesterday", "25 Days Ago", "One Month Ago"), and 6 of its 25 rows carried "Reposted" in front, which means the number is the repost age, not the first posting. Y Combinator gives nothing. Google Jobs gives a time_ago and a timestamp, but the timestamp is simply the query time minus time_ago: the row marked "14 days ago" had a timestamp exactly 14 days before the call, to the minute. Treat it as a rough age and store your collection date.
Why does the city filter not mean the city?
On Built In, 10 of the 25 rows with the Austin filter had a location like "2 Locations" or "65 Locations" instead of a city. Those are real postings listing many places, so a key that includes the city splits them. On Google Jobs the Austin query returned Houston, Plano, Tampa, Boulder and Connecticut among its ten rows, so filter the location on your side after the call.
Why does the role filter return other roles?
A filter is a category or keyword match, not a title match. Built In's "data engineer" search returned "Systems Engineer - Data Security" and "Data Center Engineer". The Y Combinator product category returned an underwriter and a deployment strategist next to the product managers.
How do you spot the same job twice?
Within one board, ids repeat nothing, but titles do: two General Motors rows on Built In were both called "Senior Data Engineer", with different ids, one showing "2 Locations" and one "Austin, TX, USA". Across boards nothing is shared: Built In ids, Y Combinator ids and Google job_id values are unrelated, and the URLs differ. Use the company plus a normalised title, with the city only when it is a real city:
def posting_key(row):
city = row.get("location", "")
if "Location" in city: # "2 Locations" is a count, not a place
city = ""
return (row["company"].lower().strip(),
row["title"].lower().strip(),
city.split(",")[0].lower().strip())
Keep the url and the board on each row so you can settle doubtful matches by hand.
📖 See also Indeed API alternatives for job search
Should you use Google Jobs instead of going board by board?
Use it to see what exists, and a board endpoint to watch it. Google Jobs gave us ten rows from six different sources in one call, billed $0.0024 (Verified 2026-10-16), so for a first look at a market, or a long tail you cannot list, one query is hard to beat.
The cost is the record. The apply link on a Google row points to wherever the copy was found, and in our run that was often a re-poster, not the employer or the board: BeBee on three of ten. Five of the ten rows carried no salary, and the employer link was empty on all ten. The listed price is $0.0012 a page (Verified 2026-10-16) and our single page billed twice that, so run one call and read the bill before you queue a hundred.
The split that works: Google Jobs to find the roles and the boards, then a board endpoint to track the ones that matter, because the board's own fields, such as Built In's seniority label or the Y Combinator batch, live there.
Which endpoint should I use for which job?
| Endpoint | What it does | Input | Returns | Billing | Price (Verified 2026-10-16) |
|---|---|---|---|---|---|
builtin/search_jobs | Built In postings, 25 per page | query, location, work_type, page | Title, company, work type, salary, seniority, posted | Per call | $0.01 |
ycombinator/search_jobs | YC startup roles by category | role | Title, salary text, company, batch, description | Per call | $0.01 |
dataforseo/serp/google-jobs | Google Jobs results | keyword, location_name, depth | Title, employer, source, salary, age | Per page of 10 | $0.0012 |
wellfound/search_jobs | Startup roles on Wellfound | role, location, page | Listing records | Per call | $0.03 |
indeed/search_jobs | Indeed results page | query, location, fromage, start | Job cards with pagination | Per call | $0.10 |
The first three rows were run on 2026-10-16. The Wellfound and Indeed rows were inspected and not run, so the table gives their inputs and prices from monid inspect and nothing about their output. The Indeed listing shows a median run time of about two minutes, so run it as a background job.
Billing shape decides how you query. Built In charges the same for a broad query and a narrow one, so ask broadly and filter afterwards. Google Jobs charges per page of 10, so depth costs more each page.
When is another route a better fit?
You need postings from one employer. The company's own careers page is the source and the board copy is a lossy version of it. If the question is whether one company is hiring, start there.
You need history. Everything here returns what is live today. For what a company was hiring a year ago you need an archive, and a collection you start now does not reach backwards.
You need a board that is not in the catalogue. Run monid discover first. If the board is not listed, a library such as JobSpy or a scraper of your own is the next step.
And the disclosure: you are reading Monid's blog and we resell these endpoints. The advice that costs nothing whoever you buy from: keep the board on every row, store the original salary string, and deduplicate on company and title, not on ids.
Conclusion
The quickest way to scrape job postings is one call per board through Monid: Built In at $0.01 a call and Y Combinator at $0.01 (Verified 2026-10-16), one key for all of them, about a minute to set up and ready inside your agent when you need it. Our three runs returned 60 rows for $0.0224.
Two things matter more than which board you pick. The fields disagree: several salary formats, a posted date that is words on one board, nothing on another and an estimate on the third, and a city that is sometimes a count. Store the original string and the board on every row. And the same role arrives twice under different ids, so deduplicate on company and normalised title.
How we estimated the time saved: building and maintaining a parser for one job board is roughly 4 to 8 hours (fetch handling, parsing, paging, and the first month of fixes), so three boards come to 12 to 24 hours. The 1 minute is the install, key and first call once you already have a Monid key.
Free next step: run monid discover -q "job board aggregator search", inspect the Built In endpoint, and make one search for the role you care about. Print the salary and posted columns first; they show what you will have to clean. Start at monid.ai.
FAQ
What is the best job scraping software?
There is no single best one, because each board holds different listings. Pick the two or three boards where your roles live and use one endpoint per board. Through Monid a Built In search is $0.01 for 25 rows (Verified 2026-10-16), with no monthly plan and no minimum top-up.
Is there an Indeed job scraper that works?
Yes: the catalogue has an Indeed search endpoint at $0.10 a call (Verified 2026-10-16), with filters for posting age, job type, experience level and excluding staffing agencies. We inspected it and did not run it, and its listed median run time is about two minutes.
Can you scrape Google Jobs?
Yes, through the Google Jobs endpoint on Monid: a keyword and a location return ten rows a page with the employer, the source site, salary when shown and the age of the posting. A page is listed at $0.0012 (Verified 2026-10-16) and our one page billed $0.0024, so test one call first.
What is JobSpy, and do I need it?
JobSpy is an open source Python library that collects postings from several job boards through one interface. It suits you if you want breadth quickly and you run your own infrastructure. The blocking, the upkeep and the addresses are yours to manage.
How do you deduplicate the same job across boards?
Use the company plus a normalised title, and add the city only when the location is a real city. Board ids are unrelated to each other and the URLs differ, so there is no shared key. Keep the board and the url on every row so you can settle doubtful matches by hand.
Published August 2026.


