DEV Community

Cover image for How to scrape Workday career sites for jobs and pay ranges with Python
Norbert Sobala
Norbert Sobala

Posted on

How to scrape Workday career sites for jobs and pay ranges with Python

Plenty of large employers run their careers page on Workday. NVIDIA, Boeing, Intel, Cisco and Pfizer all do, and the URLs end in myworkdayjobs.com. The job lists look the same everywhere, which is handy: one scraper covers all of them.

I used the Workday Jobs Scraper on Apify to pull "data engineer" openings from NVIDIA and Boeing. One run returned 40 postings with full descriptions and pay ranges in 15.7 seconds. Below is the setup, the code, and what the data looked like.

Workday jobs dataset: NVIDIA and Boeing, data engineer

What data you get

Each row is one job posting. These are the fields I used the most:

Field What it holds Example from my run
jobId Workday requisition ID JR2028539
title Job title Senior Staff Software Engineer - Data Engineering
company Workday tenant name Nvidia
hiringEntity Legal entity that hires Boeing Poland sp. z o.o. EFS
location, allLocations, country Main location, every location of a multi-site job, country US, CA, Santa Clara
remoteType Employer's own remote/hybrid/onsite label Onsite Job
employmentType Full time or part time Full time
postedText, postedDate "Posted X days ago" and the exact date 2026-10-30
salaryText, salaryMin, salaryMax, salaryCurrency, salaryPeriod Pay range parsed from the posting 200000 / 322000 / USD / year
description Full job text about 5,900 characters on average
url, applyUrl Job page and apply page
careerSiteUrl, workdayTenant Which Workday site it came from boeing.wd1.myworkdayjobs.com

Postings are company data. There are no applicant profiles or personal data in the output.

What one small run returned

Input: two companies, search text data engineer, posted in the last 30 days, 20 jobs per company.

  • 40 jobs saved, 20 per company, all full time.
  • Posting dates from 2026-10-14 to 2026-11-03.
  • 33 of 40 had a published pay range (NVIDIA 19 of 20, Boeing 14 of 20). 32 in USD, one in CAD from Boeing Vancouver.
  • Median USD range: NVIDIA $168,000 to $264,500, Boeing $126,650 to $171,350.
  • 14 postings listed more than one location. One Boeing role listed 16 US sites.
  • Countries: 34 US, 2 UK, and one each for India, Poland, Canada and Ethiopia.

The jobs without a pay range were mostly outside the US, which matches how pay-transparency laws work. One more detail I liked: a Boeing posting wrote its range as "$72.250 - $104,650" (note the dot), and the scraper still parsed salaryMin as 72250.

Main input options

Input form of the Workday Jobs Scraper

  • Companies. One per line. A Workday URL is the safest choice, for example https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite. You can also type a name (Boeing) or a website (intel.com), and the actor tries to find the career site. I typed Boeing and it resolved to boeing.wd1.myworkdayjobs.com/EXTERNAL_CAREERS without help. Auto-detection does not work for every company. When it fails, the log says so and you paste the URL.
  • Search text. Sent to Workday's own search. Leave it empty to get every job.
  • Location contains. Plain text match on the location, such as Germany, London or TX.
  • Posted within last N days. 0 means any date.
  • Max jobs per company. Workday returns at most about 2,000 results per search, so split big employers with search text.
  • Include full description. On by default. It opens each job to get the description, all locations, exact date and pay range. Turn it off if you only need titles and links.
  • Only new jobs. Each run returns only postings that earlier runs with the same company and search text did not return.

Option 1: no code

  1. Open the actor page and click Try for free.
  2. In Companies, add the career site URLs or names you care about.
  3. Set Search text (I used data engineer) and Posted within last N days (30).
  4. Set Max jobs per company to something small for a first test, like 20.
  5. Click Start. My run finished in 16 seconds.
  6. Open the Output tab and export to Excel, CSV, JSON or HTML.

No proxy is needed. Workday's public job API answered fine without one, and the proxy option is off by default.

Option 2: Python with apify-client and pandas

Install the two packages:

pip install apify-client pandas
Enter fullscreen mode Exit fullscreen mode

Then run the actor and load the results into a DataFrame:

from apify_client import ApifyClient
import pandas as pd

client = ApifyClient("YOUR_APIFY_TOKEN")

run_input = {
    "companies": [
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
        "Boeing",
    ],
    "searchText": "data engineer",
    "postedWithinDays": 30,
    "maxJobsPerCompany": 20,
    "includeDescription": True,
}

run = client.actor("flarewow/workday-jobs-scraper").call(run_input=run_input)
items = list(client.dataset(run["defaultDatasetId"]).iterate_items())
df = pd.DataFrame(items)

print(len(df), "jobs")

# Pay ranges in USD, per company
usd = df[df["salaryCurrency"] == "USD"]
print(usd.groupby("company")[["salaryMin", "salaryMax"]].median())

# Share of postings with a published range
print(df.groupby("company")["salaryMin"].apply(lambda s: s.notna().mean()))

# Multi-location jobs
df["n_locations"] = df["allLocations"].apply(
    lambda v: len(v) if isinstance(v, list) else 1
)
print(df.sort_values("n_locations", ascending=False)[["title", "n_locations"]].head())

df.drop(columns=["description"]).to_csv("workday_jobs.csv", index=False)
Enter fullscreen mode Exit fullscreen mode

On my data the first groupby printed the medians above. The description column is long, so I drop it before saving a CSV for a spreadsheet, and keep it in the DataFrame for keyword searches like df[df.description.str.contains("Spark", case=False)].

Scheduling and integrations

For monitoring, turn on Only new jobs and create a Schedule in Apify Console, for example daily at 7:00. Each run then returns only postings that earlier runs have not seen, and you pay only for those.

From there you can send results to Google Sheets, Slack, Airtable, n8n, Make or Zapier through Apify integrations, or point a webhook at your own endpoint. A setup I'd use for recruiting: one task per target company, daily schedule, new rows appended to a sheet that the team filters by location.

If a run cannot scrape any company, it ends as Failed with a message instead of an empty success. A RUN_SUMMARY record in the key-value store lists the status of each company, which makes failed schedules easy to spot.

Pricing

The actor uses pay per result: $1.50 per 1,000 jobs, plus a start fee of $0.00005 per run. Platform usage is included. You are charged only for jobs saved to the dataset, so a company that is not found costs nothing. My 40-job test cost about six cents.

Responsible use

The actor reads public job postings that companies publish on their own Workday career sites. It does not log in and does not collect applicant data. Keep volumes reasonable, respect Workday's and the employers' terms, and if you republish postings, link back to the original job page.

This tutorial was written with AI assistance and checked by the author. All numbers come from a real run of the scraper.

Top comments (0)