Career Site Jobs Feed
Pricing
from $1.00 / 1,000 jobs
Career Site Jobs Feed
Bulk export 7 million+ live jobs from 200+ ATS platforms with cursor pagination, up to 1,000 jobs per batch. Filter by occupation, location, company, industry and company size. Built for data pipelines, job boards and incremental syncs.
Pricing
from $1.00 / 1,000 jobs
Rating
5.0
(1)
Developer
Jobo
Maintained by CommunityActor stats
4
Bookmarked
66
Total users
4
Monthly active users
20 hours ago
Last modified
Categories
Features
Share
Career Site Jobs Feed — the bulk firehose for data pipelines: stream Jobo's entire index of 7 million+ live jobs across 200+ ATS platforms with cursor pagination, at up to 1,000 jobs per batch and 100,000 jobs per run. This is not a keyword-search tool (that's ATS Jobs API) — it's the fastest way to get the whole normalized inventory — career sites checked daily for new and expired listings — into your warehouse. Open the actor, hit Try for free, and run the default input (one 500-job batch) — no code or API key required.
Build your input at jobo.world/api/feed-builder. Pick job categories, occupations, companies, industries, company sizes and revenues from lists, and see how many jobs match with five samples. Its Apify tab writes this actor's input: switch the Input tab to JSON and paste it.
What does Career Site Jobs Feed do?
- Streams up to 1,000 jobs per batch with cursor pagination — versus 100 per page on the search actors
- Pulls up to 100,000 jobs in a single run (
batch_size×max_batches), looping batches automatically and stopping early when the feed is exhausted - Covers all 200+ ATS platforms in one feed — or scope with
sources, structuredlocations,work_models, job category, companies, company size, revenue and industry, and leave out sources or work models you don't want - Resumable: every completed run writes its final cursor to the
FEED_METADATAkey-value record, so the next run picks up exactly where this one stopped - Built for incremental syncs — schedule it daily with
posted_after: "1 day ago"for new jobs, orupdated_after: "1 day ago"to also catch edits, instead of full re-exports - Returns the same normalized, AI-enriched job records as every Jobo actor: de-duplicated by native job ID, geocoded locations, annual-USD salaries when pay is disclosed, typed skills, work-authorization signals when the posting mentions them
- Optionally attaches the full company profile with
include_company_details— a cross-batch cache fetches each unique company once per run - Exports to JSON, CSV, or Excel, and plugs into schedules, webhooks, Zapier, Make, and the Apify API
Which ATS platforms are covered?
200+ platforms. Two references list every one of them, with the exact ID to
pass in sources: jobo.world/docs/sources
(readable table of every provider_id and its platform name) and
GET /api/v1/providers/catalog
(the same list as JSON, no key required — build against this if you need it
programmatically).
Both are generated from Jobo's scraper registry, so newly supported platforms
appear there without an actor schema update. Leave sources empty to stream all
indexed jobs, or pass canonical provider IDs such as
["greenhouse", "lever", "ashby"] to scope a run.
sourcesis not validated. A misspelled or unsupported ID is not an error — it simply matches nothing, and the run returns0results. Copy IDs from one of the two references above rather than typing platform names.
Authentication and source visibility
You never need to provide a Jobo API key. When you run the actor in the Apify
Console, Apify handles authentication for you. When you call it through the
Apify API or an Apify client, supply only your own Apify token in the normal
token parameter or client configuration.
The actor's source files are not published. Its publisher-managed Jobo
credential is stored as an encrypted Apify Secret and injected only while the
actor runs. The credential value is absent from actor inputs, dataset output,
FEED_METADATA, source definitions, public build metadata, and logs. It is not
a customer credential and there is no Jobo key to copy, configure, or rotate.
How does cursor pagination work?
The feed uses opaque cursors. The first call omits cursor; each response returns next_cursor and has_more — pass next_cursor back to fetch the next batch:
Request → {batch_size: 1000}Response → {jobs: [...1000 rows], next_cursor: "abc123...", has_more: true}Request → {batch_size: 1000, cursor: "abc123..."}Response → {jobs: [...300 rows], next_cursor: null, has_more: false}
The actor runs this loop for you — up to max_batches times per run, stopping early when has_more comes back false — and writes the final cursor to the FEED_METADATA key in the run's key-value store so a follow-up run can resume.
After a run completes in the Apify Console, open the run and select Output →
Feed Metadata. Copy last_cursor into the next run's Pagination Cursor
input. Also check has_more: when it is false, the feed is exhausted and
last_cursor is null.
For API-driven runs, fetch the same run-specific record directly (replace
<RUN_ID> with the id returned when you started the run):
GET https://api.apify.com/v2/actor-runs/<RUN_ID>/key-value-store/records/FEED_METADATA?token=<YOUR_APIFY_TOKEN>
The synchronous run-sync-get-dataset-items endpoint returns dataset items —
the jobs — only. It does not include FEED_METADATA or the next cursor in its
JSON response. Use a normal actor run plus the endpoint above when you need to
continue into another run.
How much does it cost?
This actor uses pay-per-event pricing: you pay a fixed rate per job record returned — the current rate is in the pricing box on this page. There are no separate compute, proxy, or storage charges, and a run never returns more than batch_size × max_batches rows, so spend is fully predictable. Apify's free plan includes enough credit to pull thousands of jobs, so you can evaluate the full dataset before paying anything.
How do I run a full export?
- Open the actor and click Try for free — you'll need a free Apify account.
- Smoke-test with the defaults — one batch of 500 jobs (
batch_size: 500,max_batches: 1) lets you inspect the record shape cheaply. - Scope the feed (optional): pick
sources, structuredlocations,work_models, job category, companies, company size or revenue, or aposted_afterwindow. Try the combination first at jobo.world/api/feed-builder, which shows how many jobs it matches and writes the input JSON for you. Rememberbatch_size×max_batchesis your spend ceiling. - Scale up and Start —
batch_size: 1000,max_batches: 100pulls up to 100,000 jobs in one run; the actor loops batches automatically and stops when the feed reports no more pages. - Export or resume — download JSON, CSV, or Excel from the Output tab, then open Output → Feed Metadata and copy
last_cursorinto the next run's Pagination Cursor field.
⬇️ Input
| Parameter | Type | Description |
|---|---|---|
batch_size | integer | Jobs per batch, 1–1,000 (default 500). |
max_batches | integer | Batches to pull this run, 1–100 (default 1). |
cursor | string | Opaque cursor from a previous run's FEED_METADATA. Omit to start from the beginning. |
locations | array | Structured location filters — {country, region?, city?} objects; jobs match ANY entry. A bare string is treated as a country. |
sources | array | ATS slugs to include (e.g. ["greenhouse", "lever"]). Empty = all 200+. IDs: jobo.world/docs/sources — unknown IDs match nothing rather than erroring. |
exclude_sources | array | ATS slugs to leave out (e.g. ["workday"]); may be combined with sources. |
work_models | array | remote, hybrid, onsite. |
exclude_work_models | array | Work models to leave out; jobs whose work model is unknown are kept. |
employment_types / exclude_employment_types | array | full-time, part-time, contract, internship, freelance, temporary. |
experience_levels / exclude_experience_levels | array | intern, entry, mid, senior, lead, executive. |
languages / exclude_languages | array | Description language as ISO 639-1 codes (en, de); names such as English work too. |
job_categories / job_subcategories | array | What kind of job, picked from a list (e.g. Healthcare, Nursing). exclude_job_categories / exclude_job_subcategories leave them out. |
occupation_ids | array | Exact occupations by id, from the occupation.id of any result. Browse categories, subcategories and occupation ids at jobo.world/api/feed-builder. exclude_occupation_ids leaves them out. |
companies_include / companies_exclude | array | Jobo company id, website domain (fedex.com) or whole company name (FedEx), case-insensitive. Entries that match no company are logged as warnings; if no include entry matches, the run returns no jobs. |
company_sizes / company_revenues | array | Employee and revenue bands, picked from a list (e.g. 51-200, 10m-50m). exclude_company_sizes / exclude_company_revenues leave them out. |
industries / exclude_industries | array | Company industries, copied from company.industries of any result. |
company_primary_industries / exclude_company_primary_industries | array | The company's primary industry, copied from company.primary_industry. |
company_categories / exclude_company_categories | array | Company categories such as B2B or SaaS. |
staffing_agencies | string | exclude to leave out jobs posted by recruitment agencies, only for just theirs. |
posted_after | string | ISO 8601 (2026-01-01) or relative (1 day ago): jobs first posted after this date. |
include_reactivated | boolean | With posted_after, also return jobs that came back online after that date (default false). |
updated_after | string | ISO 8601 or relative: jobs created, updated or re-indexed since then. The recommended incremental-sync watermark, because it also catches edits to jobs you already have. |
include_company_details | boolean | Attach the full enriched company profile; a cross-batch cache fetches each unique company once per run (default false). |
description_format | string | markdown (default) or html. enhanced and enhanced_html (beta) return the same words with consistent headings, lists and key facts; a job without an enhanced description returns its standard one. |
Note the locations format: unlike the search actors, which take free-text location strings and geocode them server-side, the feed takes structured objects so filtering stays exact at bulk scale:
"locations": [{ "country": "United States" },{ "country": "Germany", "region": "Bavaria" },{ "country": "United Kingdom", "city": "London" }]
The full input schema with defaults is on this page's Input schema tab.
⬆️ Output example
Results land in the dataset under two views: Job Feed (all sources) (one row per job) and Company details (populated when include_company_details is on). Every row is the same normalized record shape as ATS Jobs API and the single-ATS actors — the source field carries the slug of the ATS each job came from (here "greenhouse"; a feed batch mixes all the platforms you include). A typical record:
A job whose company is part of a brand (a franchisee, an independent agent or agency, a hotel under a hotel group's flag) also carries a brand object with id, name, domain and logo_url. The key is omitted otherwise.
{"id": "f0f6a7d0-c667-48f7-95bc-a91f172e2d6d","title": "Software Engineer","normalized_title": "Software Engineer","occupation": {"id": "esco:f2b15a0e-e65a-438a-affb-29b9d50b77d1","name": "Software Engineer","category": "Technology","subcategory": "Software Engineering","isco_code": "2512","onet_soc_codes": ["15-1252.00"]},"summary": "Design and develop software for capital equipment and medical devices used by cardiac surgeons and electrophysiologists…","company": {"id": "6647fb14-d420-434a-a332-9c972016b9b0","name": "AtriCure","website": "https://atricure.com","logo_url": "https://images.jobo.world/logos/atricure.jpg","industries": ["Medical Devices & Equipment"],"details_url": "https://connect.jobo.world/api/companies/6647fb14-d420-434a-a332-9c972016b9b0"},"locations": [{"location": "Minneapolis, MN","city": "Minneapolis","region": "Minnesota","country": "United States","latitude": 44.9772995,"longitude": -93.2654692}],"compensation": { "min": 71036, "max": 104186, "currency": "USD", "period": "yearly" },"employment_type": "Full-time","workplace_type": "On-site","experience_level": "Mid Level","qualifications": {"must_have": {"education": ["Bachelor's degree in Systems Engineering, Electrical Engineering, or Computer Engineering"],"skills": [{ "name": "C", "type": "hard" },{ "name": "C++", "type": "hard" },{ "name": "Software Development Methodologies", "type": "hard" }]},"preferred": {"skills": [{ "name": "Rust", "type": "hard" },{ "name": "Python", "type": "hard" }]}},"is_work_auth_required": true,"listing_url": "https://job-boards.greenhouse.io/atricure/jobs/4309998009","apply_url": "https://job-boards.greenhouse.io/atricure/jobs/4309998009#app","source": "greenhouse","date_posted": "2026-07-09T13:47:14Z","description": "…full job description, HTML stripped…"}
How do I resume and sync incrementally?
Every successful run writes a FEED_METADATA record to its key-value store.
In the Console, open the completed run and choose Output → Feed Metadata:
{"total_jobs": 100000,"batches_processed": 100,"last_cursor": "eyJsYXN0X2lkIjoi…","has_more": true}
last_cursor is only set while has_more is true; once the feed is exhausted it's null and you're done.
From the Apify API, read the same record without first resolving a key-value store ID:
GET https://api.apify.com/v2/actor-runs/<RUN_ID>/key-value-store/records/FEED_METADATA?token=<YOUR_APIFY_TOKEN>
Worked example — a multi-run full export. Run 1 starts from the top:
{ "batch_size": 1000, "max_batches": 100 }
Run 1 finishes with has_more: true and a last_cursor in FEED_METADATA. Run 2 carries that cursor over:
{"batch_size": 1000,"max_batches": 100,"cursor": "eyJsYXN0X2lkIjoi…"}
Repeat until has_more comes back false.
Daily incremental sync. Create an Apify Schedule that runs this actor every 24 hours with:
{"batch_size": 1000,"max_batches": 100,"posted_after": "1 day ago"}
Each scheduled run then pulls only jobs posted since the previous one — far cheaper than re-paginating the full feed.
To also pick up edits to jobs you already have (new salary, changed description, a job that came back online), use updated_after instead: it returns every job created, updated or re-indexed since then. It returns more records than posted_after, so it costs more per run, but your copy stays current.
{"batch_size": 1000,"max_batches": 100,"updated_after": "1 day ago"}
What can you expect from a run?
- Hard ceiling: 100,000 jobs per run — 100
max_batches× 1,000batch_size. For more, chain runs by passinglast_cursoras the next run'scursor. - Pacing: the actor waits 0.5 seconds between batches to keep the feed healthy.
- On a 503, the actor honors the API's
Retry-Afterheader and retries automatically; if it persists, check jobo.world/status. - Cursors are opaque — pass them back exactly as returned; don't construct or edit them. A stale cursor from an old run may be rejected — omit it to restart from the beginning.
- No keyword, salary, or skills filters — the feed is a firehose by design. For search and faceted filtering, use ATS Jobs API.
- Freshness: Jobo checks every tracked career site daily for new and expired listings; jobs removed from the employer's site drop out of the feed.
Integrations, API & MCP
Everything on the Apify platform works out of the box: schedules (hourly/daily/weekly runs), webhooks on run completion, and one-click integrations with Zapier, Make, n8n, Slack, Google Sheets, and Google Drive.
Prefer code? Call this actor as a bulk jobs feed API from Python or JavaScript with the Apify API clients — start a run, wait for it, and page through the dataset in a few lines (ready-made snippets are in the API section of this page). AI agents can run it through the Apify MCP server, which exposes this actor as a tool.
Use cases
| Who | What for |
|---|---|
| Data platforms | Sync millions of normalized jobs into a warehouse or lakehouse for analytics |
| Job boards | Backfill and refresh a full job index with cross-ATS coverage |
| Search infrastructure | Build a custom job search engine on top of the raw feed |
| HR tech | Market-intel pipelines fed by bulk daily syncs |
| AI training | Job-data corpora for embeddings, fine-tunes, and classifiers |
| Competitive intel | Track hiring velocity across companies and sectors at full-market scale |
❓ FAQ
Should I use this actor or ATS Jobs API?
Use ATS Jobs API for filtered, paginated queries — keyword search, salary and skills filters, up to 100 pages × 100 results. Use this actor for bulk download and sync: cursor pagination, 1,000 jobs per batch, built for ETL pipelines and warehouses.
How fast is it? What's the maximum throughput?
One run pulls up to 100,000 jobs (batch_size: 1000 × max_batches: 100), with a 0.5-second pause between batches. For the full index, chain runs — each run's FEED_METADATA hands the next one its starting cursor.
How do I resume a long export?
Open the previous run's Output → Feed Metadata, copy last_cursor, and pass it as cursor in the next run. API callers can GET /v2/actor-runs/<RUN_ID>/key-value-store/records/FEED_METADATA. When has_more is false, you've reached the end. The synchronous dataset-items response contains jobs only, not the cursor.
Can batches overlap or skip jobs?
Within a run, consecutive batches never overlap — the cursor encodes the exact feed position. Across resumed runs the cursor picks up where you left off, but the index is live: jobs added or expired in between follow the daily career-site checks.
Are duplicate listings removed?
Yes. Listings are de-duplicated by the source ATS's native job ID within each employer. A role an employer posts on two different ATS platforms appears once per platform.
How fresh is the data?
New jobs on any of the 200+ platforms are picked up on the next daily check. Jobo checks every tracked career site daily for new and expired listings, and jobs removed from the employer's site drop out of the feed.
Where can I check if the API behind this actor is up?
At jobo.world/status — the live status page for the Jobo Connect API that powers every Jobo actor.
⚖️ Is it legal to scrape ATS job listings?
Jobo only collects job postings employers publish publicly on their career sites, and returns no personal data about candidates. Postings can still incidentally contain personal data (e.g., a recruiter's name in a job description), which the GDPR and similar regulations protect, so only process it with a legitimate reason. Whether a use is lawful depends on your jurisdiction and use case, so check with your counsel for anything sensitive. Read more in Apify's guide to the legality of web scraping.
All ATS names are trademarks of their respective owners. This actor is an independent product and is not affiliated with, endorsed by, or sponsored by any of them.
🔗 Related actors
| Actor | Best for |
|---|---|
| ATS Jobs API | Search 200+ ATS platforms in one call |
| AI Deep Job Search | Describe your ideal job in plain English, get AI-scored matches |
| Greenhouse Jobs Scraper | 220,000+ jobs from tech companies on Greenhouse |
| Workday Jobs Scraper | 1.2 million+ jobs from Fortune 500 employers on Workday |
| Lever Jobs Scraper | 75,000+ jobs from VC-backed startups on Lever |
About Jobo & support
Jobo builds job-data infrastructure: a normalized index of jobs built from daily checks of company ATS career sites, powering job boards, AI agents, and HR-tech products.
- Questions or bugs? Open a ticket on this actor's Issues tab and we'll follow up.
- Website: jobo.world · Enterprise API: jobo.world/enterprise · API status: jobo.world/status
- Email: enrico@jobo.world