Extract public job postings from company career pages and linked applicant tracking system (ATS) job pages. Use it to monitor hiring signals, build recruiting lead lists, enrich company data, or track labor-market changes without manually checking every careers page.
Value proposition
Career Page Job Postings Scraper turns messy public careers pages into a clean job-posting dataset you can plug into recruiting, sales, market-intelligence, and alerting workflows.
What does it do?
- Starts from one or more public company careers URLs.
- Detects job posting links on the page.
- Optionally follows linked public job detail pages.
- Normalizes every saved job into one dataset with consistent fields.
- Keeps going when one URL is blocked or returns no jobs, so you can process mixed lists safely.
Example input
{
"startUrls": [
{ "url": "https://stripe.com/jobs/search" },
{ "url": "https://www.notion.com/careers" }
],
"maxItems": 50,
"maxPagesPerSite": 25,
"includeDetails": true,
"sameDomainOnly": true,
"keywords": ["engineer", "sales"],
"excludeKeywords": ["intern"]
}
Example output
{
"companyName": "Notion",
"sourceUrl": "https://www.notion.com/careers",
"jobUrl": "https://jobs.ashbyhq.com/notion/05e14247-17c4-4e98-9a13-53828a4e2f13",
"title": "Outbound Business Development Representative, AMER",
"department": null,
"team": null,
"location": "New York, New York",
"workplaceType": null,
"employmentType": null,
"postedAt": null,
"descriptionText": null,
"applyUrl": "https://jobs.ashbyhq.com/notion/05e14247-17c4-4e98-9a13-53828a4e2f13",
"salaryText": null,
"atsVendor": "ashbyhq",
"extractionMethod": "job-link",
"scrapedAt": "2026-07-12T14:02:42.961Z"
}
Input settings
| Field | Type | Description |
|---|---|---|
startUrls |
array | Public career page URLs to scan. |
maxItems |
integer | Maximum saved job records across all URLs. |
maxPagesPerSite |
integer | Maximum pages fetched per start URL, including linked job detail pages. |
includeDetails |
boolean | Follow detected public job pages to enrich records when possible. |
keywords |
array | Save only jobs matching at least one keyword in title, URL, location, or description. |
excludeKeywords |
array | Skip jobs matching any excluded keyword. |
sameDomainOnly |
boolean | Follow same-domain links plus recognized public ATS job hosts linked from the career page. |
resumePending |
boolean | Continue the source URLs recorded in PENDING_WORK after a prior run ended its time budget. |
Who is it for
- Recruiting teams tracking hiring demand across target companies.
- Sales and lead generation teams looking for expansion or budget signals.
- Labor-market analysts monitoring role, department, and location trends.
- Data teams that need repeatable career-page data in a normalized format.
Use cases
- Monitor target accounts for new hiring signals.
- Build recruiter sourcing lists from public company websites.
- Track competitor hiring by department, location, or role family.
- Feed data warehouses with normalized public job posting records.
- Trigger alerts when target companies add matching roles.
Tips for best results
- Use public careers or jobs pages, not login-only applicant portals.
- Greenhouse, Lever, and Ashby board URLs use their public job-listing responses when available; other public career pages use bounded page discovery.
- Keep
sameDomainOnlyenabled unless you intentionally want broader crawling. - Use
keywordsto focus large career sites on specific teams or roles. - Increase
maxPagesPerSitefor companies with many paginated job listings.
Limits and responsible use
The actor only works with publicly reachable job listings. It does not use user cookies, private accounts, paid credentials, applicant records, or application endpoints. It rejects private/local network URLs and reports blocked, challenge, unavailable, and all-source failures instead of treating them as successful empty exports. A multi-source run can retain valid rows while recording failed sources in RUN_SUMMARY; a hard deadline saves PENDING_WORK for an opt-in follow-up run.
API usage
JavaScript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('<ANNA_APIFY_USERNAME>/career-page-job-postings-scraper').call({
startUrls: [{ url: 'https://stripe.com/jobs/search' }],
maxItems: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
Python
from apify_client import ApifyClient
client = ApifyClient('YOUR_APIFY_TOKEN')
run = client.actor('<ANNA_APIFY_USERNAME>/career-page-job-postings-scraper').call(run_input={
'startUrls': [{'url': 'https://stripe.com/jobs/search'}],
'maxItems': 50,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
cURL
curl -X POST "https://api.apify.com/v2/acts/<ANNA_APIFY_USERNAME>~career-page-job-postings-scraper/runs?token=$APIFY_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"startUrls":[{"url":"https://stripe.com/jobs/search"}],"maxItems":50}'
MCP and agent usage
Use this actor from Apify MCP to let AI agents monitor career pages and retrieve structured job postings. Connect compatible AI clients through https://mcp.apify.com/?tools=<ANNA_APIFY_USERNAME>/career-page-job-postings-scraper.
CLI setup:
claude mcp add --transport http apify "https://mcp.apify.com/?tools=<ANNA_APIFY_USERNAME>/career-page-job-postings-scraper"
JSON config example:
{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com/?tools=<ANNA_APIFY_USERNAME>/career-page-job-postings-scraper"
}
}
}
Example prompts:
- "Find public sales and engineering jobs from these company career pages."
- "Monitor this list of career URLs and return new remote roles."
- "Extract normalized job postings and include job URLs and locations."
Support
Questions or missing fields? Open an issue on the actor page and include:
- The run ID or run URL.
- The input JSON you used.
- The public career page URL you expected to scrape.
- The expected output and actual output you received.
- Any reproducible public URL that demonstrates the missing or incorrect job data.