Skip to content

Job Listings API - Any Careers Site to JSON

Rocketyard’s Job Listings API extracts job posting data from any website that publishes schema.org JobPosting markup and returns one clean record per job posting: title, description, date posted, valid through, employment type, company and more. It runs on the Apify platform, so you can start it from the Apify Console, the REST API, an AI agent or a no-code tool.

  • Recruiters and staffing agencies tracking competitor openings
  • Sales teams using hiring as a buying signal
  • Developers building job boards and salary tools
  • Collect job postings (title, location, salary) from any career site without a scraper per site
  • Monitor which companies are hiring for which roles
  • Build a job dataset for analysis or AI

Websites publish schema.org JobPosting markup (JSON-LD or microdata) so search engines can show rich results. The Actor fetches each page over plain HTTP without a browser, honours robots.txt and crawl-delay, reads that markup and maps it to the fields below. Because it reads the markup rather than the page layout, one Actor works across many sites and keeps working through redesigns. Give it a list of URLs, or a start page and let it crawl links on the same site.

A real record from a test run on job-boards.greenhouse.io on 2026-11-11. Fields the page didn’t publish are left out here; the Actor returns them as null. The same test also read jobs.lever.co.

{
"url": "https://job-boards.greenhouse.io/discord/jobs/8722538002",
"type": "JobPosting",
"title": "Engineering Manager, Machine Learning (Safety)",
"description": "Discord has a highly engaged community of millions of daily active users who use the platform for many different reasons, but there’s one thing that nearly everyone does: play video games. Discord plays a uniquely important role in the future of gaming, and we are focused on making it easier and…",
"datePosted": "2026-08-20T13:43:23-04:00",
"company": "Discord",
"location": "Remote (US)",
"remote": "TELECOMMUTE",
"salaryCurrency": "USD",
"salaryMin": 272000,
"salaryMax": 340000,
"identifier": "8722538002",
"scrapedAt": "2026-11-11T13:03:57.099Z"
}
Field Read from (schema.org) Filled in latest test
title title 100%
description description 100%
datePosted datePosted 100%
validThrough validThrough 0%
employmentType employmentType 33%
company hiringOrganization.name, hiringOrganization 100%
companyUrl hiringOrganization.sameAs, hiringOrganization.url 0%
location jobLocation.address.addressLocality, jobLocation.address 100%
region jobLocation.address.addressRegion 0%
country jobLocation.address.addressCountry 0%
remote jobLocationType 33%
salaryCurrency baseSalary.currency 33%
salaryMin baseSalary.value.minValue 33%
salaryMax baseSalary.value.maxValue 33%
salaryUnit baseSalary.value.unitText 0%
identifier identifier.value, identifier 33%
url the page the record came from 100%
scrapedAt ISO timestamp of the extraction 100%

A field is filled when the source publishes it. The Actor never guesses a value: a missing field comes back as null. “Filled in latest test” is the share of records from the latest test run (job-boards.greenhouse.io and jobs.lever.co) that had the field; other sources publish more or less.

You pay $1.00 per 1,000 results, plus a start fee of $0.00005 per run. Pages without JobPosting markup produce a free error item instead of a record.

Results Cost
1,000 $1.00
10,000 $10.00
100,000 $100.00

Set maxItems or the run’s Maximum cost per run in Apify to cap spending.

Every Apify Actor is also a REST endpoint, so Job Listings API works as a job postings API, a job listings API or a career site jobs API. Call it from any language with the Apify REST API, or with Apify’s JavaScript and Python clients. You need an Apify API token.

Terminal window
curl -s -X POST "https://api.apify.com/v2/acts/rocketyard~jobposting-schema-scraper/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H 'content-type: application/json' \
-d '{"startUrls":[{"url":"https://jobs.lever.co/spotify/03437e2a-2d5e-4593-9e97-11271014932e"}],"maxItems":100}'
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('rocketyard/jobposting-schema-scraper').call({"startUrls":[{"url":"https://jobs.lever.co/spotify/03437e2a-2d5e-4593-9e97-11271014932e"}],"maxItems":100});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("rocketyard/jobposting-schema-scraper").call(run_input={"startUrls":[{"url":"https://jobs.lever.co/spotify/03437e2a-2d5e-4593-9e97-11271014932e"}],"maxItems":100})
items = client.dataset(run["defaultDatasetId"]).list_items().items

The synchronous endpoint returns the records directly. For long crawls, start the run asynchronously and read the dataset when it finishes.

Apify’s MCP server exposes this Actor as a tool to Claude, Cursor and other MCP clients. Open this Actor’s MCP setup page for setup steps per client, or connect it with this URL:

https://mcp.apify.com?tools=rocketyard/jobposting-schema-scraper

Claude Code:

Terminal window
claude mcp add --transport http apify "https://mcp.apify.com?tools=rocketyard/jobposting-schema-scraper"

Cursor (.cursor/mcp.json) and other clients that read an mcpServers config:

{
"mcpServers": {
"apify": { "url": "https://mcp.apify.com?tools=rocketyard/jobposting-schema-scraper" }
}
}

On first use your browser opens so you can sign in to Apify. Then ask the agent, for example: “Collect job postings (title, location, salary) from any career site without a scraper per site”. The tool returns JSON records, and the runs are billed to that Apify account at $1.00 per 1,000 results.

n8n, Make and Zapier all connect to Apify. Each example below uses Actor rocketyard/jobposting-schema-scraper with this input:

{
"startUrls": [
{
"url": "https://jobs.lever.co/spotify/03437e2a-2d5e-4593-9e97-11271014932e"
}
],
"maxItems": 100
}

Copy this workflow and paste it onto an n8n canvas. It runs the Actor every morning through an HTTP Request node and returns the records as n8n items.

{
"name": "Job Listings API daily",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "days",
"daysInterval": 1,
"triggerAtHour": 7
}
]
}
},
"id": "c1f6a2d0-4a57-4b5e-9d7a-0a1b2c3d4e01",
"name": "Every day at 07:00",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
0,
0
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.apify.com/v2/acts/rocketyard~jobposting-schema-scraper/run-sync-get-dataset-items",
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "{\n \"startUrls\": [\n {\n \"url\": \"https://jobs.lever.co/spotify/03437e2a-2d5e-4593-9e97-11271014932e\"\n }\n ],\n \"maxItems\": 100\n}",
"options": {
"timeout": 300000
}
},
"id": "c1f6a2d0-4a57-4b5e-9d7a-0a1b2c3d4e02",
"name": "Run Job Listings API",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
260,
0
],
"credentials": {
"httpBearerAuth": {
"name": "Apify API token"
}
}
}
],
"connections": {
"Every day at 07:00": {
"main": [
[
{
"node": "Run Job Listings API",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {}
}

Then open the HTTP Request node and create an HTTP Bearer Auth credential named Apify API token, with your token from Apify Console as the bearer token. The token stays in n8n’s credential store; the workflow only names the credential. Change the input in the node’s JSON body to your own.

The node waits up to 300 seconds, which is also the limit of Apify’s synchronous endpoint. An input that yields nothing comes back as an item with an error field, which you can drop with a Filter node. Apify also publishes a community node, @apify/n8n-nodes-apify, with a Run an Actor and get dataset operation.

  1. Add Apify’s Run an Actor module and connect your Apify account.
  2. Choose rocketyard/jobposting-schema-scraper, paste the input above and set Run synchronously to Yes. Make limits how long a synchronous run can take, depending on your plan. For longer runs, start the scenario from Watch Actor Runs instead.
  3. Add Get Dataset Items with the run’s default dataset ID.
  4. Send the items wherever you need them, for example with Google Sheets Add a Row, mapping title, description, datePosted and validThrough.
  1. Add Apify’s Run Actor action, connect your Apify account, choose rocketyard/jobposting-schema-scraper and paste the input above.
  2. Zapier stops synchronous runs after 30 seconds. For anything larger than a small run, let the run continue in the background and start a second Zap from the Finished Actor run trigger.
  3. Add Fetch dataset items with the run’s dataset ID, then map title, description, datePosted and validThrough into your app.
  4. Test with a small input and check that the Zap handles every record before you turn it on.
  • Pages without schema.org JobPosting markup return no record.
  • Markup added only by JavaScript in the browser is not read: the Actor reads the HTML the server sends.
  • Pages behind a login or paywall are not accessed, and paths that robots.txt disallows are skipped.

$1.00 per 1,000 results plus $0.00005 per run, billed by Apify. 10,000 results cost $10.00. There is no subscription, and you can cap any run with Maximum cost per run.

Your Apify plan sets your discount tier (Platinum and Diamond are enterprise tiers):

Tier Per 1,000 results
Free $1.00
Bronze $1.00
Silver $0.80
Gold $0.65
Platinum $0.65
Diamond $0.65

One request starts a run and returns its results, using your Apify API token:

Terminal window
curl -X POST "https://api.apify.com/v2/acts/rocketyard~jobposting-schema-scraper/run-sync-get-dataset-items" -H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" -d '{"startUrls":[{"url":"https://jobs.lever.co/spotify/03437e2a-2d5e-4593-9e97-11271014932e"}],"maxItems":100}'

The dataset gets one free error item for it, with a code and the reason, and the other inputs in the run carry on. Error codes explains each code, whether a retry helps and what to do.

Any public page that publishes schema.org JobPosting data in its HTML. Most modern sites add it for Google rich results.

The field comes back as null. The Actor reports what the source publishes and never fills in guesses.

The Actor reads public pages only, obeys robots.txt and crawl-delay, doesn’t log in or bypass protections, and doesn’t collect people’s profiles, personal emails or personal phone numbers. You are responsible for how you use the data under each site’s terms and the law (for example copyright and GDPR).

Yes. Connect Apify’s MCP server as shown in MCP, and the agent can call the Actor as a tool.

See how it compares with other job posting scrapers on price, users and run success, from Apify Store data. Need a field or site behaviour that isn’t covered? Open an issue on the Actor page.