Workable Jobs Scraper avatar

Workable Jobs Scraper

Pricing

from $0.84 / 1,000 results

Go to Apify Store
Workable Jobs Scraper

Workable Jobs Scraper

Jobs from any company's Workable job board (apply.workable.com/<account>) via the public API: title, departments, location(s), on-site/hybrid/remote, employment type, experience, industry, posted date, apply URL and full description. Search by keyword; filter by department, location, remote.

Pricing

from $0.84 / 1,000 results

Rating

0.0

(0)

Developer

Ibnu Adzim

Ibnu Adzim

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Categories

Share

Every open job on any company's Workable job board — Viva.com, Skroutz, Blueground and the thousands of others hosted at apply.workable.com/<account> — through Workable's public apply API: title, departments, location(s) with country code, on-site / hybrid / remote, employment type, experience level, function, industry, posted date, apply URL and the full description (requirements and benefits inline) as text and HTML.

HTTP only, no login, no key, no browser. The list is walked 10 jobs per page by cursor; one extra request per account brings every description.

What it is for

  • Company watchlists — a list of accounts on a schedule, diff by shortcode.
  • Keyword search across companiessearchTerms uses Workable's own search, one walk per account × term, de-duplicated.
  • Remote / department / city slicesremoteOnly is server-side; departments and locations are local substring filters.

Input

fieldwhat it does
accountsAccount slugs (viva) or URLs (apply.workable.com/viva/, a job URL under the account). A bare apply.workable.com/j/<shortcode> link carries no account and is refused.
searchTermsSent to Workable's search; empty = whole board.
departments, locations, remoteOnlyFilters (see #3 below for why two are local).
includeDescriptionOn by default; one widget request per account.
maxItems, maxConcurrency, minRequestInterval, proxyConfigurationLimits.

Each account × term gets a BOARD_SUMMARY with Workable's reported total, the pages walked, how many rows carry a description, what the filters dropped, and the board's own department and location vocabularies.

Four things about this API worth knowing before you trust a run

1. A bad or stale cursor restarts the walk from page one — with HTTP 200

token=zzzz answers the first page again, with the same nextPage an untokened call returns. A walker that loops on nextPage alone never ends. The Actor remembers every cursor and every page's shortcodes; a repeat stops the walk with stoppedReason: cursor_loop.

2. The legacy widget duplicates multi-location jobs and mislabels a field

The one-call description source (

www.workable.com/api/accounts/<account> ?details=true
) lists one row per location: Viva.com shows 44 rows for 40 jobs, same shortcode. Its state field is the region name ("Attica"), not the job state. The Actor uses it only for descriptions and taxonomy, first row per shortcode, and never reads its state; the v3 list is the record of what exists.

3. The server-side filters are typed, and a string is a 400

department: ["Direct Sales"]400 "department[0]" must be a number; worktype: ["zzqq"]400 does not match any of the allowed types. Only the free-text query and the boolean remote flag are ever sent; departments / locations are matched locally against the board's own words (departmentsOnBoard in the summary is the vocabulary).

4. An account with no public jobs is 200 {"total":0}; an unknown account is a bare 404

hotjar, typeform → total 0 (they exist on Workable). zzqqnotanacct404 Not Found. Reported as empty_board (or no_matches under a query) vs account_not_found.

Other things measured

  • published is midnight UTC — date precision only. createdAt comes from the widget.
  • employmentType (full / part / contract / temporary) is absent on some rows; the widget's label (Full-time) is kept beside it.
  • A full last page still carries a nextPage; the page after it is empty. pagesWalked can be ceil(total/10) + 1.
  • No throttling or anti-bot layer seen; a page is ~5 KB, the widget ~5 KB per job.

Output

  • JOBjobId, shortcode, title, url, applyUrl, departments, employmentType, employmentTypeLabel, workplace, isRemote, location, locationDetail, locations, language, requisitionCode, published, createdAt, experience, education, function, industry, description, descriptionHtml, account, resultPosition.
  • BOARD_SUMMARYaccount, boardUrl, query, totalJobsReported, jobsReturned, pagesWalked, rowsWithDescription, widgetRows, stoppedReason (exhausted, max_items, empty_board, no_matches, cursor_loop, max_pages), filteredOut, departmentsOnBoard, locationsOnBoard.
  • ERRORinvalid_input, account_not_found, descriptions_unavailable (widget failed; JOB rows still shipped), payload_shape_changed, fetch_failed, with detail.

Known limits

  • Salary is not a field on either endpoint; it appears only inside descriptions when the company writes it.
  • searchTerms are Workable's search, not a local match; what it indexes is Workable's choice.
  • Internal / unlisted postings are not served.