Workable Jobs Scraper — Search 170K Jobs, No Slug avatar

Workable Jobs Scraper — Search 170K Jobs, No Slug

Pricing

from $1.00 / 1,000 job results

Go to Apify Store
Workable Jobs Scraper — Search 170K Jobs, No Slug

Workable Jobs Scraper — Search 170K Jobs, No Slug

Search all ~170,000 live Workable jobs by keyword, location, workplace type and recency — no company slug needed — or scrape specific company boards. Multi-country postings are billed once, not once per country. Delta monitoring, BYOK AI enrichment, MCP-ready.

Pricing

from $1.00 / 1,000 job results

Rating

0.0

(0)

Developer

Nomad Dev

Nomad Dev

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Claude / Codex skill to describe and setup this actor: SKILL.md

Search every job on Workable by keyword — you do not need to know a company slug. Workable's public index carries roughly 170,000 live postings from tens of thousands of SMBs and scale-ups; this Actor searches all of it, or scrapes specific company boards directly if you already know who you want.

No login, no API key, no proxies. Public APIs only.

{ "searchQuery": "python engineer", "searchWorkplace": "remote", "postedWithin": "7d" }

That's a complete run. No slug hunting.

Why this one

Most Workable scrapers make you supply a company slug — so you can't use them until you already know which companies you want. The ones that do search have a quieter problem, and it's on your invoice.

Workable's index lists a posting once per country it's open in — each copy with its own id and URL, all the same job. One posting in a recent run was listed in 36 countries. A scraper that reads the index literally returns that job 36 times and bills you 36 times.

This Actor folds them back into one row per real job, every country in a locations array. Measured on a live run: 46 jobs returned, 46 results billed — those 46 jobs occupy 363 rows in Workable's index. Billed per row, the same jobs cost 7.9× more. On a broad unfiltered search, roughly a third of index rows are duplicates; on a narrow one it's far more.

This Actor
Search all of Workable, no slug
Scrape specific company boards✅ (batch, many at once)
One row per job, not per country✅ — the 7.9× above
workplace (remote / hybrid / on-site)✅ stated by Workable, not guessed
Full description + requirements + benefits
Company website (lead-gen)✅ on every row

Two ways to run it

1. Search (no slug needed) — the whole Workable index:

{
"searchQuery": "registered nurse",
"searchLocation": "London",
"searchWorkplace": "hybrid",
"postedWithin": "14d",
"maxItems": 100
}

2. Company boards — when you already know the companies:

{ "companies": ["netguru", "typeform"], "keyword": "engineer" }

Find a slug by opening the company's careers page and reading it out of apply.workable.com/<slug>/. Full board URLs work too — they're reduced to the slug for you. You can combine both modes in one run; a posting found by both is returned (and billed) once.

Input

FieldTypeDefaultDescription
searchQuerystringFree-text search across every job on Workable — no company slug needed. e.g. python engineer.
searchLocationstringCity, region or country to search in, e.g. London, Germany.
searchWorkplacestringanyany / remote / hybrid / on_site. An exact filter — Workable states this per posting.
companiesarrayOptional. Workable board slugs (full board URLs also accepted).
keywordstringCase-insensitive substring match on the job title. Applies to both modes.
titleExcludearrayDrop postings whose title contains any of these substrings.
locationFilterstringCase-insensitive substring match on the location.
postedWithinstringanyKeep only jobs published inside this window. Use any for no date filter, or a duration — 1h, 24h, 3d, 2w, 6m. Jobs the source gave no date for are dropped rather than guessed at. Covers both the board crawl and the search query, which used to take separate recency inputs. Replaces postedSince, searchPostedDays, still accepted for existing integrations.
remoteOnlybooleanfalseFully-remote only. Hybrid is not counted as remote — use searchWorkplace for that.
includeDescriptionbooleantrueInclude the full plain-text description. Turn off for lighter output.
maxItemsPerCompanyinteger100Cap postings per company board (0 = no cap). Each result is billed.
maxItemsinteger200Hard cap on total postings returned (0 = no cap). Each result is billed. In search mode this also bounds how deep the Actor pages.
concurrencyinteger8Company boards fetched in parallel (advanced).

Output

Every row follows nomad-agent-job-row-v1, the one shape shared by all of this fleet's job Actors. A row carries every field; null means the source did not publish that fact, and locations: [] means no usable location was parsed from the posting. Nothing is guessed.

{
"schemaVersion": "nomad-agent-job-row-v1",
"recordType": "posting",
"source": "workable",
"id": "a1b2c3",
"url": "https://example.com/workable/jobs/a1b2c3",
"title": "Senior Backend Engineer",
"company": "Example Company",
"locations": [
"Bilbao",
"Spain"
],
"postedAt": "2026-09-02T00:00:00Z",
"deadline": "2026-10-15",
"description": "The complete posting body as plain text, exactly as the source published it — never truncated.",
"descriptionHtml": "<p>The complete posting body as the source's own markup.</p>",
"workType": "remote",
"custom": {
"schemaId": "nomad-agent-job-custom-workable-v1",
"data": {
"globalId": "…",
"department": "…",
"applyUrl": "…"
}
}
}
FieldMeaning
schemaVersionAlways "nomad-agent-job-row-v1".
recordType"posting" for a job, "diagnostic" for a row reporting something about the run itself.
sourceWhich job source the posting came from, from the collector registry's vocabulary — not the Actor name.
idStable identifier for the posting within source.
urlCanonical public URL of the posting on the source site.
titleJob title exactly as the source publishes it, untruncated.
companyEmployer name as published.
locationsPlaces the role is based, most specific first — e.g. ["Bilbao", "Spain"].
postedAtWhen the source published the posting, ISO-8601 UTC (YYYY-MM-DDTHH:MM:SSZ).
deadlineClosing date for applications as an ISO-8601 calendar date (YYYY-MM-DD).
descriptionThe complete posting body as plain text — never truncated, never summarised.
descriptionHtmlThe posting body as the source's own markup, preserving lists, headings and links.
workTypeWorking arrangement: "remote", "hybrid" or "onsite".
customFacts only this source publishes, as {"schemaId", "data"}.

A run also emits diagnostic rows — recordType: "diagnostic" with a warnings array — when it has something to report, such as a source returning nothing. They are never billed and are easy to filter out on recordType.

Call it from code

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("nomad-agent/workable-jobs-scraper").call(run_input={
"searchQuery": "python engineer",
"searchWorkplace": "remote",
"maxItems": 50,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["company"], "|", item["title"], "|", item["workplace"], item["url"])
curl -X POST \
"https://api.apify.com/v2/acts/nomad-agent~workable-jobs-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"searchQuery": "python engineer", "searchWorkplace": "remote"}'

Output example

{
"ats": "workable",
"company": "payabl.",
"companyWebsite": "http://payabl.com",
"id": "5b10e8f7-627e-4cd3-8f09-3c40c96f71f5",
"title": "Senior Backend Python Engineer (Core Gateway)",
"department": "Engineering",
"location": "Czechia",
"locations": ["Czechia", "Germany", "United Kingdom", "Romania", "Serbia", "Netherlands"],
"locationCountry": "Czechia",
"url": "https://jobs.workable.com/view/cfdWh7wNW4V1G8zXPmvN1n/...",
"applyUrl": "https://jobs.workable.com/view/cfdWh7wNW4V1G8zXPmvN1n/...",
"postedAt": "2026-06-22",
"employmentType": "Full-time",
"workplace": "remote",
"remote": true,
"snippet": "About payabl. We are a fast-growing fintech...",
"requirements": "5+ years of Python...",
"benefits": "Private health insurance...",
"globalId": "workable:search:5b10e8f7-627e-4cd3-8f09-3c40c96f71f5",
"warnings": []
}

That is one row. A scraper that reads Workable's index literally would have returned it six times — once per country — and billed you six times.

Warning rows

Diagnostic rows use schemaVersion: "nomad-agent-job-row-v1", recordType: "diagnostic", a warnings array and optional docs. They carry no posting fields and are not billed as job results. A dataset consumer can filter them by recordType:

TriggerExample warnings
A requested company slug 404'd["not found on any ATS probed (workable): 'acme-corp' (404 on every probe)"]
maxItemsPerCompany cut postings for one company["truncated for 'acme-corp': maxItemsPerCompany=100 returned 100 of 137 matching postings"]
maxItems cut the run["truncated: maxItems=200 returned 200 of 3401 matching postings"]

None of these rows are billed — only genuine postings are.

Integrations

Export as JSON, CSV or Excel, or pipe into Make, Zapier or n8n. Call it synchronously with run-sync-get-dataset-items, or plug it into any AI agent through the Apify MCP server.

Pricing

Pay per event — the current rate is shown in the Pricing section of this page. No subscription, no minimum.

Compare on cost per real job, not cost per row. Workable's index repeats a multi-country posting once per country, and a scraper that bills per index row bills you for every one of them. A real run of this Actor: 46 jobs returned, 46 results billed — but those 46 jobs occupy 363 rows in Workable's index (one posting alone is open in 36 countries). Billed per row, the same 46 jobs cost 7.9× more.

So a cheaper-looking headline rate is often the more expensive scraper.

Use cases

  • Find who's hiring for a role across all of Workable, without a company list
  • Recruiting-agency lead generation (company website on every row)
  • Job-board aggregation and new-posting alerts by comparing scheduled snapshots downstream
  • Hiring/market research on SMBs and scale-ups (Workable is strong in Europe)

FAQ

Do I need a company slug? No. searchQuery searches every company on Workable. Slugs are optional, for when you want specific boards.

Is it legal to scrape Workable jobs? The data comes from Workable's official, public, unauthenticated JSON APIs — the same data any visitor sees on a careers page. Review the terms for your use case.

Do I need an API key or login? No. Public APIs, no authentication of any kind.

Why does one job list several countries? Because it's open in all of them. Workable's index repeats such a posting once per country; this Actor returns it once with every country in locations, so you aren't billed repeatedly for the same job.

How fresh is the data? Every run hits Workable live. No caching layer in between.

Something broken or missing? Open an issue on the Issues tab — it's monitored and fixes ship fast.


From the maker of Oink — an open-source, AI-powered job-search bot for Telegram that runs on these Actors. Try the free bot, get a managed instance at oinkjobsearch.com, or browse the full catalog of 50+ Actors.