# Workday Jobs Scraper | Career Change Feed (`danthedataman/workday-career-ledger`) Actor

Export public Workday career sites with job details, locations and available salary fields. Compare full snapshots for new, changed and observed-closed jobs.

- **URL**: https://apify.com/danthedataman/workday-career-ledger.md
- **Developed by:** [Eli J](https://apify.com/danthedataman) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.08 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What you can export

Use this **Workday jobs and career-site scraper** for recruiting research and hiring monitoring. Supply public career-site URLs to export openings, descriptions, locations and available compensation fields.

Compare complete, unfiltered snapshots for new, changed and observed-closed jobs. Check `SITE_SUMMARY` before treating a collection as complete; a missing job is not called closed after a capped, filtered or failed read.

### Try the example input

Paste public Workday careers URLs into `startUrls`. Both `company.wdN.myworkdayjobs.com/site` and `wdN.myworkdaysite.com/recruiting/company/site` are supported, including locale and job-page URLs. Multiple boards share one dataset.

```json
{
  "startUrls": [
    {
      "url": "https://austintexas.wd5.myworkdayjobs.com/COA_Careers"
    },
    {
      "url": "https://wd5.myworkdaysite.com/recruiting/microchiphr/External"
    }
  ],
  "maxJobsPerSite": 10
}
```

The example limits output to ten rows per site. Remove that limit, or set it to `0`, for all matching rows. An omitted `startUrls` never starts example work: `{}` succeeds with guidance and no job requests.

### Inputs

| Field | Type | Default | Meaning |
| --- | --- | --- | --- |
| `startUrls` | array | none | Public Workday URLs as strings or `{url}` objects in the JSON editor; supports multiple boards. |
| `companies` | array | `[]` | Bundled mapped names, public domains or careers URLs. Unknown names go to ERRORS. |
| `inputUrl` | string | none | Public UTF-8 CSV, XLSX or Google Sheet; cells may contain the same URLs/names. |
| `searchText` | string | empty | Workday's own keyword search. |
| `appliedFacets` | object | `{}` | Facet parameter names mapped to arrays of source IDs from SITE_SUMMARY. |
| `titleKeywords` | array | `[]` | Case-insensitive OR literal substrings in job titles. |
| `locationKeywords` | array | `[]` | OR literal substrings across primary and additional locations. |
| `descriptionKeywords` | array | `[]` | AND literal substrings across title and full description; requires details. |
| `remoteOnly` | boolean | `false` | Only explicit remote roles; unknown and hybrid excluded. |
| `employmentType` | string | none | Case-insensitive literal stem in source timeType, such as `full` or `part`. |
| `postedAfter` | string | none | Inclusive YYYY-MM-DD using exact source startDate; ignored with a warning in list-only mode. |
| `includeDetails` | boolean | `true` | Full descriptions and detail fields; false reads listing fields only. |
| `includeRawJson` | boolean | `false` | Adds the original detail response, or list object, as `raw`. |
| `maxJobsPerSite` | integer | `0` | Output rows per site; 0 means unlimited. Example prefill uses 10. |
| `maxItems` | integer | none | Global output cap; 0 means no job reads or rows. |
| `detailConcurrency` | integer | `5` | 1–10 simultaneous detail requests per batch. |
| `maxRetriesPerRequest` | integer | `3` | 1–5 total attempts; fresh cookies and proxy session for each attempt. |
| `maxRunSeconds` | integer | `900` | Positive source-read budget, up to 86,400 seconds. Each request has a terminating deadline of at most 20 seconds, including DNS and response reads. |
| `proxyConfiguration` | object | Apify datacenter | Omitted starts with BUYPROXIES94952; alternate-family details retry through residential after a transport failure and reuse that route for the board. `useApifyProxy:false` uses direct egress; supplied settings are respected. |
| `baselineDatasetId` | string | none | Read-only full snapshot dataset from this Actor; enable dataset READ permission. |

Names are matched without punctuation or case. The bundled map contains 3,282 Workday tenant names and 4,896 career sites, including City of Austin and Microchip; availability can change. Use the tenant name shown in a Workday URL, or one of the mapped organization aliases. A careers-domain URL is inspected for public Workday links or redirects and up to two same-origin careers links. If discovery finds several boards, supply the intended URLs directly. Each unique canonical board is read once.

```json
{"companies": ["City of Austin", "microchip"], "titleKeywords": ["engineer", "analyst"], "maxItems": 50}
```

```json
{"companies": ["https://www.austintexas.gov/services/apply-city-job"], "includeDetails": false, "maxJobsPerSite": 20}
```

For spreadsheets, use `{"inputUrl":"https://your-public-host.example/workday-boards.csv"}`. A header such as `company,url` is optional. Reads are limited to 5 MB, 10,000 cells and 10 MB of expanded XLSX XML. There is no login or private-sheet access.

### 27 request examples

Replace the public file host, Google Sheet ID and baseline dataset ID placeholders with your own resources. The job-page example reads its board, not only that one job. Filters may match no jobs. Capped examples cannot be used as full baselines. Example 23 produces the full-detail baseline for example 27; grant READ access to that dataset. These are input bodies, not published Store tasks.

| # | Request | Input |
| --- | --- | --- |
| 1 | One board, URL string | `{"startUrls":["https://austintexas.wd5.myworkdayjobs.com/COA_Careers"],"maxJobsPerSite":10}` |
| 2 | Alternate family, URL object | `{"startUrls":[{"url":"https://wd5.myworkdaysite.com/recruiting/microchiphr/External"}],"maxJobsPerSite":10}` |
| 3 | Multiple boards | `{"startUrls":["https://austintexas.wd5.myworkdayjobs.com/COA_Careers","https://wd5.myworkdaysite.com/recruiting/microchiphr/External"],"maxJobsPerSite":10}` |
| 4 | Locale-bearing board | `{"startUrls":["https://austintexas.wd5.myworkdayjobs.com/en-US/COA_Careers"],"maxJobsPerSite":10}` |
| 5 | Job-page URL resolves its board | `{"startUrls":["https://wd5.myworkdaysite.com/recruiting/microchiphr/External/job/CT---Simsbury/Production-Specialist--Solder-_R2902-26"],"maxJobsPerSite":10}` |
| 6 | Mapped organization | `{"companies":["City of Austin"],"maxJobsPerSite":10}` |
| 7 | Mapped tenant | `{"companies":["microchip"],"maxJobsPerSite":10}` |
| 8 | Multiple mapped names | `{"companies":["City of Austin","microchip"],"maxJobsPerSite":10}` |
| 9 | Careers-page discovery | `{"companies":["https://www.austintexas.gov/services/apply-city-job"],"maxJobsPerSite":10}` |
| 10 | Public CSV intake | `{"inputUrl":"https://your-public-host.example/workday-boards.csv","maxJobsPerSite":10}` |
| 11 | Public XLSX intake | `{"inputUrl":"https://your-public-host.example/workday-boards.xlsx","maxJobsPerSite":10}` |
| 12 | Public Google Sheet | `{"inputUrl":"https://docs.google.com/spreadsheets/d/YOUR_PUBLIC_SHEET_ID/edit#gid=0","maxJobsPerSite":10}` |
| 13 | Listing fields only | `{"companies":["City of Austin"],"maxJobsPerSite":10,"includeDetails":false}` |
| 14 | Original detail JSON | `{"companies":["City of Austin"],"maxJobsPerSite":10,"includeRawJson":true}` |
| 15 | Source keyword search | `{"companies":["City of Austin"],"maxJobsPerSite":10,"searchText":"engineer"}` |
| 16 | Title OR filter | `{"companies":["City of Austin"],"maxJobsPerSite":10,"titleKeywords":["engineer","analyst"]}` |
| 17 | Location OR filter | `{"companies":["City of Austin"],"maxJobsPerSite":10,"locationKeywords":["Austin","Texas"]}` |
| 18 | Description AND filter | `{"companies":["City of Austin"],"maxJobsPerSite":10,"descriptionKeywords":["benefits","experience"]}` |
| 19 | Explicit remote jobs | `{"companies":["City of Austin"],"maxJobsPerSite":10,"remoteOnly":true}` |
| 20 | Employment-type stem | `{"companies":["City of Austin"],"maxJobsPerSite":10,"employmentType":"full"}` |
| 21 | Inclusive source date | `{"companies":["City of Austin"],"maxJobsPerSite":10,"postedAfter":"2026-10-01"}` |
| 22 | Global output limit | `{"startUrls":["https://austintexas.wd5.myworkdayjobs.com/COA_Careers","https://wd5.myworkdaysite.com/recruiting/microchiphr/External"],"maxItems":10}` |
| 23 | Full detail snapshot for a baseline | `{"companies":["City of Austin"]}` |
| 24 | Full-depth large-board listing | `{"companies":["target"],"includeDetails":false,"maxRunSeconds":2700}` |
| 25 | Ten concurrent detail slots | `{"companies":["City of Austin"],"maxJobsPerSite":10,"detailConcurrency":10,"maxRetriesPerRequest":2}` |
| 26 | Direct egress with a time budget | `{"companies":["City of Austin"],"maxJobsPerSite":10,"proxyConfiguration":{"useApifyProxy":false},"maxRunSeconds":120}` |
| 27 | Read-only snapshot changes | `{"companies":["City of Austin"],"baselineDatasetId":"YOUR_FULL_SNAPSHOT_DATASET_ID"}` |

Example 24 uses a 2,700-second source-read budget. For a large board, set the Actor's platform run timeout to at least 3,600 seconds with 256 MB of memory; `maxRunSeconds` does not extend the platform run timeout.

### Output

One dataset row is one job, or one observed job change. Example values below illustrate the shape; they are not a currently advertised vacancy.

```json
{
  "recordType": "job",
  "title": "Senior C++ Engineer",
  "company": "Acme Incorporated",
  "tenant": "acme",
  "siteId": "External",
  "sourceUrl": "https://acme.wd5.myworkdayjobs.com/External",
  "url": "https://acme.wd5.myworkdayjobs.com/External/job/West/Senior-C-Engineer_R123",
  "applyUrl": "https://acme.wd5.myworkdayjobs.com/External/job/West/Senior-C-Engineer_R123/apply",
  "jobReqId": "R123",
  "locations": ["West Office", "East Office"],
  "postedDate": "2026-06-01",
  "descriptionText": "Salary: $80,000 - $120,000 per year.\nResponsibilities\nBuild & test.\nQualifications\nC++ skills.",
  "salaryMin": 80000,
  "salaryMax": 120000,
  "salaryCurrency": "USD",
  "salaryUnit": "YEAR",
  "scrapedAt": "2026-10-06T17:00:00Z"
}
```

| Field | What it contains |
| --- | --- |
| `recordType` | `job` for a snapshot or `jobChange` for a comparison. |
| `snapshotEligible` | True only for uncapped, unfiltered full-detail snapshot settings with no source error observed before this row. Baseline import additionally verifies full per-board row counts. False on changes. |
| `detailUnavailable` | True when the source lists only a requisition ID or the requested detail returns 404. Only actual list facts are retained; missing title and links are null. The measured reason is in ERRORS. |
| `title`, `company` | Source title and hiring organization; tenant used if no organization name is published. |
| `tenant`, `siteId`, `sourceUrl` | Canonical Workday board identity and URL. |
| `url`, `applyUrl` | Public job page and its Workday `/apply` link; no application is opened or submitted. |
| `atsPlatform`, `seniority` | `workday`; first explicit title word among intern, junior, senior, staff, lead, principal, director and executive, or null. |
| `city`, `region`, `locationCount` | Explicit comma-delimited location tokens; null for ambiguous prose. Count from a source `N Locations` label, or null. No geocoding. |
| `jobReqId`, `jobPostingId`, `workdayInternalId` | Source requisition, posting and internal IDs. |
| `locationsText`, `primaryLocation`, `additionalLocations`, `locations` | List summary plus every published detail location; no geocoding. |
| `country`, `countryCode` | Published country descriptor and alpha2Code. |
| `postedOn`, `postedDate`, `endDate`, `timeLeftToApply` | Relative label, exact source startDate/endDate and deadline label. |
| `timeType`, `remoteType`, `isRemote`, `workArrangement` | Source employment/remote type; normalized remote, hybrid or onsite when explicit. |
| `canApply` | Source application-availability boolean. |
| `descriptionHtml`, `descriptionText` | Full original HTML and readable, entity-decoded text; null in list-only mode. |
| `responsibilities`, `qualifications` | Text under recognized description headings, or null. |
| `salaryText`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryUnit` | First explicit published range. Amounts retain their HOUR/DAY/WEEK/MONTH/YEAR period; no annualization or predicted pay. |
| `scrapedAt`, `totalJobsOnSite` | UTC observation timestamp and source-count target for this query, including count-verified facet partitions. |
| `raw` | Optional original source payload. |
| `changeStatus`, `changedFields` | Change-only: new, changed or closed, with sorted changed source fields. |

Missing source values are null. Pay and remote status are not inferred from a model. Available job descriptions are retained even if section detection finds no headings. Source-listed postings with unavailable details count toward jobs read and coverage; they cannot be baseline rows or produce changes. Other valid jobs and later partitions continue. Their missing metadata makes SITE_SUMMARY incomplete for snapshot comparisons.

### Snapshot changes

Save a full, unfiltered snapshot with details and no output cap, then pass its dataset ID as `baselineDatasetId` with READ permission. Only new or changed current rows are delivered; unchanged rows are suppressed. A job absent from a completely collected current board is emitted as `closed`, with its previous values and the current observation timestamp.

```json
{
  "startUrls": [{"url": "https://austintexas.wd5.myworkdayjobs.com/COA_Careers"}],
  "baselineDatasetId": "YOUR_PREVIOUS_FULL_SNAPSHOT_DATASET_ID"
}
```

A change feed is not a full snapshot and cannot be reused as a baseline. Capped, filtered or list-only baselines are rejected: every row must have `snapshotEligible:true`, and each board must have full descriptions and as many unique rows as its recorded source total. Baselines missing that flag are rejected with guidance in ERRORS. Current comparisons require details. Relative posting-age and deadline labels do not create billable changes; exact dates remain comparison fields. Empty baselines make every current job new and produce a warning. Baselines are never changed. A missing job is never called closed after a capped, filtered, list-only, interrupted or failed collection. Closure is an observation, not the source's deletion time.

### Coverage and completion

Detail batches share one HTTP worker. Each read uses a fresh cookie and proxy session. A request deadline terminates the worker and its pending reads, then uses the bounded retry policy; unfinished jobs are recorded in ERRORS.

This Actor reads anonymous public Workday career sites. It does not read application accounts or login-only jobs. Workday sometimes returns the same zero-job response for an invalid board and an empty board; a zero result therefore does not prove an employer has no vacancies.

Pagination uses the first query count, twenty jobs per page and unique requisition identities. When source facets expose a larger count than the list cap, the Actor partitions by count-covering facet values and verifies the final unique union. No usable partition, moving counts, repeated pages, failed details or a time budget mark the collection incomplete. Inspect SITE_SUMMARY before treating any result as a complete snapshot. Date filtering scans all pages because job dates are not reliably sorted.

SITE_SUMMARY contains per-site source counts, jobs read, rows delivered, completion and raw facets, plus response bytes, request count and a charge/cap stop flag. ERRORS contains unresolved inputs and safe read-failure reasons. Both are unbilled run records, separate from the dataset. A valid zero or unmatched filter succeeds with guidance; a run where every attempt fails and no row is delivered fails. Mixed runs retain valid jobs.

Blocked/rate-limited, server-error and malformed answers receive bounded retries on fresh sessions. Rejected requests (400/404/422) stop immediately. Default egress is Apify datacenter; choose residential only where a blocked board requires it and account for its transfer cost. A binding customer charge limit stops new work; requests already in flight may finish.

The results are live observations. The Actor supplies no historical global database, AI/company/contact enrichment or other ATS adapters. See the current Pricing tab for event prices.

# Changelog

This Actor's version history is a separate document: https://apify.com/danthedataman/workday-career-ledger/changelog.md

# Actor input Schema

## `startUrls` (type: `array`):

Public Workday boards or job URLs from either URL family. API callers may send URL strings or url objects. No default work.

## `companies` (type: `array`):

Verified mapped names, public domains or careers URLs. Unresolved names go to ERRORS.

## `inputUrl` (type: `string`):

Public UTF-8 CSV, XLSX or Google Sheet with board URLs or company names. 5 MB, 10,000 cells, 10 MB expanded XML maximum.

## `searchText` (type: `string`):

Source keyword search passed to Workday.

## `appliedFacets` (type: `object`):

Source facetParameter keys mapped to arrays of IDs from SITE_SUMMARY.

## `titleKeywords` (type: `array`):

Case-insensitive OR literal substrings in titles.

## `locationKeywords` (type: `array`):

Case-insensitive OR substrings across all source locations.

## `descriptionKeywords` (type: `array`):

AND literal substrings across title and full text. Requires includeDetails.

## `remoteOnly` (type: `boolean`):

Only explicitly remote roles; unknown and hybrid excluded.

## `postedAfter` (type: `string`):

Inclusive YYYY-MM-DD on source startDate. Ignored with warning in list-only mode.

## `includeDetails` (type: `boolean`):

HTML and plain-text descriptions, dates and published source fields. False avoids detail requests.

## `includeRawJson` (type: `boolean`):

Add raw detail response, or list object in list-only mode.

## `maxJobsPerSite` (type: `integer`):

0 means unlimited matching output rows. Example prefill caps each site at 10.

## `maxItems` (type: `integer`):

Optional global output cap. 0 produces no job reads or rows.

## `detailConcurrency` (type: `integer`):

Details in flight per batch. No new reads after a binding charge result; existing calls can finish.

## `maxRetriesPerRequest` (type: `integer`):

Total classified attempts, fresh cookies and proxy session per attempt. 400/404/422 are not retried.

## `maxRunSeconds` (type: `integer`):

Monotonic budget for new reads and retries. Per-read timeout is at most 20 seconds. Incomplete boards cannot close jobs.

## `proxyConfiguration` (type: `object`):

Omitted starts with datacenter BUYPROXIES94952; alternate-family detail transport failures may retry through residential. Explicit useApifyProxy:false uses direct egress; supplied settings are respected.

## `baselineDatasetId` (type: `string`):

Optional read-only snapshot from this Actor. Authorize dataset READ. Emits only new/changed/closed jobs; never infer closure from partial collections.

## `employmentType` (type: `string`):

Case-insensitive literal stem in source timeType, such as full or part.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://austintexas.wd5.myworkdayjobs.com/COA_Careers"
    },
    {
      "url": "https://wd5.myworkdaysite.com/recruiting/microchiphr/External"
    }
  ],
  "companies": [],
  "searchText": "",
  "appliedFacets": {},
  "titleKeywords": [],
  "locationKeywords": [],
  "descriptionKeywords": [],
  "remoteOnly": false,
  "includeDetails": true,
  "includeRawJson": false,
  "maxJobsPerSite": 10,
  "detailConcurrency": 5,
  "maxRetriesPerRequest": 3,
  "maxRunSeconds": 900
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `errors` (type: `string`):

No description

## `sites` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        {
            "url": "https://austintexas.wd5.myworkdayjobs.com/COA_Careers"
        },
        {
            "url": "https://wd5.myworkdaysite.com/recruiting/microchiphr/External"
        }
    ],
    "maxJobsPerSite": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("danthedataman/workday-career-ledger").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "startUrls": [
        { "url": "https://austintexas.wd5.myworkdayjobs.com/COA_Careers" },
        { "url": "https://wd5.myworkdaysite.com/recruiting/microchiphr/External" },
    ],
    "maxJobsPerSite": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("danthedataman/workday-career-ledger").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://austintexas.wd5.myworkdayjobs.com/COA_Careers"
    },
    {
      "url": "https://wd5.myworkdaysite.com/recruiting/microchiphr/External"
    }
  ],
  "maxJobsPerSite": 10
}' |
apify call danthedataman/workday-career-ledger --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,danthedataman/workday-career-ledger"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/b62kCyz4Odh4H95sW/builds/d2GcWYRTMzfzCHcaq/openapi.json
