Workday Jobs Scraper for myworkdayjobs.com avatar

Workday Jobs Scraper for myworkdayjobs.com

Pricing

from $0.75 / 1,000 results

Go to Apify Store
Workday Jobs Scraper for myworkdayjobs.com

Workday Jobs Scraper for myworkdayjobs.com

Reads any Workday careers site on myworkdayjobs.com through the tenant's own CXS search API and returns the requisition ID, title, employmentType, isRemote, postedAt, apply URL and a location split into city, state and country. Paginates a whole board 20 postings at a time.

Pricing

from $0.75 / 1,000 results

Rating

0.0

(0)

Developer

String

String

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

14 days ago

Last modified

Share

What does Workday Job Board Scraper do?

A Workday careers site is a React shell. Load one and the served HTML has no postings in it at all. Every board is backed by the tenant's own CXS search API, which answers an unauthenticated POST with the same JSON the site renders from, and that API is what this Actor reads.

Hand it a careers-site URL such as https://salesforce.wd12.myworkdayjobs.com/External_Career_Site and it returns the board's postings with requisition id, title, employment type, remote flag, posted date, apply URL, and a location split into city, state and country.

Nothing is per-company. A Workday address encodes everything needed: the host names the tenant and its shard (salesforce.wd12), and the first path segment names the board (External_Career_Site). Those two rebuild the API path for any board on the platform.

  • The board page, a locale-prefixed page such as /en-US/External_Career_Site, a link to one posting, and the CXS endpoint itself all collapse to the same board and cost one fetch.
  • Workday answers HTTP_400 to any page larger than 20 postings, so a full board is always paginated 20 at a time, stopping at the board's own reported total.
  • Pages are scheduled only while rows are still wanted, so a hundred boards under a thousand-row cap fetch a thousand rows rather than a hundred boards in full.
  • No Workday account, cookie or API key. This is the external careers site a logged-out visitor sees.

What data does it extract?

FieldTypeDescription
jobIdstringWorkday's requisition id as printed under the posting title, for example JR284401
titlestringThe posting title
companystringAlways null. See the FAQ
tenantstringThe Workday tenant, read from the host, for example salesforce
locationstringThe displayed location, verbatim. May read 3 Locations when a posting is open in several offices
citystringResolved from the location, or from the posting's own URL when the display location is absent or says 3 Locations
statestringUS state or Canadian province code
countrystringISO 3166 alpha-2 code
isRemotebooleantrue when the location or Workday's remoteType names remote, virtual, home office or telecommute
departmentstringAlways null. See the FAQ
employmentTypestringWorkday's timeType, for example Full time
postedAtstringCalendar date, YYYY-MM-DD, reconstructed from Workday's relative label
jobUrlstringDirect link to the posting
boardUrlstringThe careers site a person would open
sourceUrlstringThe CXS endpoint the row came from
collectedAtstringISO 8601 timestamp of the run

How the location is resolved

Workday tenants write the same address every way round. Reno, NV, USA.VA.Reston,

California - San Francisco
and USA TX Houston Virtual are all real forms from production boards.

So the parts are recovered by punctuation first, falling back to whitespace only when the tenant used none, and then each part is resolved by what it is rather than by where it sits. That is why Denver, CO, USA and USA, CA, Pleasanton both come out correctly. A two-letter part is tried as a US or Canadian region before a country, so the CO in Denver, CO, USA stays Colorado instead of becoming Colombia. The trade is that a bare CA always reads as California.

Fragments that describe how a role is worked rather than where it sits, like Virtual or

Home Office
, are read for the remote flag and then dropped, which leaves the city behind. A trailing building code in parentheses is discarded, and sales-region labels such as EMEA and APAC are allowed to be neither a city nor a country.

How postedAt is derived

The search API publishes no timestamp. It publishes Posted 4 Days Ago, so the date is reconstructed against the run's own clock. Posted 30+ Days Ago is left null on purpose: the plus is an open bound, and dating it exactly 30 days back would invent a day the board never claimed.

Why scrape Workday?

Workday is the ATS of large employers. If you are tracking hiring at enterprises, this is where the requisitions actually live, and the CXS API returns them as clean JSON rather than as rendered markup.

  • Monitor enterprise headcount direction across a named competitor set, run on a schedule.
  • Detect a new site or market entry from where requisitions start appearing.
  • Feed a job board or talent CRM directly from the employer's board, keyed on a stable jobId.
  • Build recruiting lists filtered on city, state, country or isRemote.
  • Score sales accounts on hiring signals, weighting by postedAt freshness.
  • Track how much of a large employer's hiring is genuinely remote, using the flag rather than the title.

How to use it

  1. Follow the employer's "careers" or "search jobs" link until the address bar shows <tenant>.wd<N>.myworkdayjobs.com/<Board>. Copy the URL. A single posting's URL works too.
  2. Add it to Job boards, up to 100 per run.
  3. Set Maximum results. Boards paginate 20 at a time, so this is what bounds the request count.
  4. Raise Concurrency toward 10 when collecting many boards.
  5. Run it, then export the dataset as JSON, CSV, Excel or XML, or read it over the API.

Input

FieldTypeDefaultDescription
boardsarray of stringsrequiredWorkday careers-site URLs on myworkdayjobs.com. Between 1 and 100 entries
maxItemsinteger1000Cap on dataset rows, up to 50,000
concurrencyinteger5Requests in flight at once, up to 10
{
"boards": [
"https://salesforce.wd12.myworkdayjobs.com/External_Career_Site",
"https://nvidia.wd5.myworkdayjobs.com/en-US/NVIDIAExternalCareerSite"
],
"maxItems": 3000,
"concurrency": 5
}

Board segments are compared case-insensitively, so /Ames and /ames are one board rather than two identical fetches. A host outside myworkdayjobs.com is rejected with a reason instead of fetched.

Output

One row per posting. Illustrative shape:

{
"jobId": "JR284401",
"title": "Lead Solution Engineer",
"company": null,
"tenant": "salesforce",
"location": "California - San Francisco",
"city": "San Francisco",
"state": "CA",
"country": "US",
"isRemote": false,
"department": null,
"employmentType": "Full time",
"postedAt": "2026-08-16",
"jobUrl": "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site/job/California---San-Francisco/Lead-Solution-Engineer_JR284401",
"boardUrl": "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site",
"sourceUrl": "https://salesforce.wd12.myworkdayjobs.com/wday/cxs/salesforce/External_Career_Site/jobs",
"collectedAt": "2026-08-20T09:14:02.118Z"
}

The run also writes a SUMMARY record holding the item count, the failure count and each failed board or page with its error.

How much does it cost?

Pay per event, charged once per result row written to the dataset. The current rate is on this Actor's pricing tab, and a board that is rejected writes no rows and costs nothing.

At 20 postings per request, requests track rows closely, so maxItems is effectively the budget dial. Collecting the first 200 postings of fifty boards is much cheaper than collecting fifty boards in full, and the scheduler here is built to make that first case work rather than fetching everything and throwing the surplus away.

Runs started from an Apify free plan stop at 250 requests and 250 results and report the limit in the run status. Any paid plan runs the full input. Because pagination turns one board into many fetches, the second pass of a free-plan run is bounded against whatever the first pass left rather than against the full allowance again.

Using it with the Apify API

import { ApifyClient } from "apify-client";
const client = new ApifyClient({ token: "<YOUR_APIFY_TOKEN>" });
const run = await client.actor("usestring/workday-jobs").call({
boards: ["https://salesforce.wd12.myworkdayjobs.com/External_Career_Site"],
maxItems: 3000,
concurrency: 5
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const remoteShare = items.filter((job) => job.isRemote).length / items.length;
console.log(`${items.length} postings, ${(remoteShare * 100).toFixed(1)}% remote`);

Read the run's SUMMARY record from its key-value store to see which boards, if any, were rejected.

An external Workday careers site is published so candidates and search engines can find open roles. This Actor calls the same unauthenticated CXS endpoint the public site calls, with no account, no session cookie and no API key. Internal Workday instances, which require a login, are out of reach and out of scope.

The output describes requisitions, not people. No applicant data, no application counts, no recruiter contacts. company and department are null because Workday publishes neither, so there is nothing personal or proprietary being reconstructed here.

Local law and the terms you have agreed to still govern what you may do with collected data. This is context, not legal advice.

FAQ

How do I find a company's Workday careers site? Follow the careers link on the employer's own site. Workday sites look like https://<tenant>.wd<N>.myworkdayjobs.com/<Board>, where <N> is a data-centre number. Paste the whole URL, or paste a single posting's URL and let the Actor reduce it to the board.

How many postings come back per request? Twenty. Workday rejects anything larger with HTTP_400, so a 2,000-posting board is 100 requests and there is no way around that.

Why is there no company name? Workday publishes none on any public endpoint. The search response has no such field, and the detail endpoint carries only the hiring legal entity, which is often something like 4 LZB Retail, Inc. rather than the brand a person would recognise. Rather than fill the column with something misleading it is left null, and tenant is the identity to join on.

Why is there no department? For the same reason. Department exists on a Workday board only as the jobFamilyGroup facet, which counts how many postings sit in each category without naming the category of any individual posting.

How accurate is postedAt? It is exact for anything posted within the last 30 days, since Posted 4 Days Ago resolves to a real calendar date against the run clock. Beyond that Workday only says 30+ Days Ago, and the field is null.

Do results ever duplicate? They are de-duplicated on jobUrl before being written, which is necessary because a board whose reported total understates it hands back page one again past the end instead of terminating.

What happens if a board rejects the search? Workday answers a rejected search with an error envelope carrying its own httpStatus inside a 200 response, so it would otherwise look like a successful empty board. That envelope is read, and the board is recorded under failures in the run's SUMMARY.

Feedback

If a board returns nothing, or a location splits into the wrong fields, open an issue from this Actor's Store page with the board URL. Workday location strings vary more than anything else here, and a real example is what it takes to handle a new form.