<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: makerio</title>
    <description>The latest articles on DEV Community by makerio (@makerio).</description>
    <link>https://dev.to/makerio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4246492%2Ffcc9d0b9-8fae-45c5-b387-7969beae12d7.jpg</url>
      <title>DEV Community: makerio</title>
      <link>https://dev.to/makerio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/makerio"/>
    <language>en</language>
    <item>
      <title>Every Workday career site has a public JSON API. Here is how to get all its jobs</title>
      <dc:creator>makerio</dc:creator>
      <pubDate>Sun, 15 Nov 2026 20:02:28 +0000</pubDate>
      <link>https://dev.to/makerio/every-workday-career-site-has-a-public-json-api-here-is-how-to-get-all-its-jobs-4jl0</link>
      <guid>https://dev.to/makerio/every-workday-career-site-has-a-public-json-api-here-is-how-to-get-all-its-jobs-4jl0</guid>
      <description>&lt;p&gt;NVIDIA, CVS Health, Wells Fargo, Northrop Grumman and thousands of other large employers post their jobs on Workday. You know these sites by the address: &lt;code&gt;something.wd5.myworkdayjobs.com/SomeCareerSite&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The page itself is a JavaScript app, so fetching its HTML gives you almost nothing. But the app loads every job from a small JSON API, and that API is public: no login, no key, no cookies. It is the same request your browser makes when you open the site. This post shows how to use it, and the four gotchas that will silently cost you jobs if you do not know about them.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Read the three parts from the URL
&lt;/h2&gt;

&lt;p&gt;Open the company's careers page, click any job, and look at the address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://nvidia.wd5.myworkdayjobs.com/en-US/NVIDIAExternalCareerSite/job/US-CA-Santa-Clara/...
        ^^^^^^ ^^^                         ^^^^^^^^^^^^^^^^^^^^^^^^
        tenant data center                 site
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;tenant&lt;/strong&gt;: the company's code, &lt;code&gt;nvidia&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;data center&lt;/strong&gt;: &lt;code&gt;wd1&lt;/code&gt;, &lt;code&gt;wd3&lt;/code&gt;, &lt;code&gt;wd5&lt;/code&gt;, &lt;code&gt;wd12&lt;/code&gt; and so on&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;site&lt;/strong&gt;: the career site name, &lt;code&gt;NVIDIAExternalCareerSite&lt;/code&gt;. Skip the language part (&lt;code&gt;en-US&lt;/code&gt;) if there is one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You cannot guess these from the company name. NVIDIA is &lt;code&gt;nvidia.wd5/NVIDIAExternalCareerSite&lt;/code&gt;, Northrop Grumman is &lt;code&gt;ngc.wd1/Northrop_Grumman_External_Site&lt;/code&gt;, Wells Fargo is &lt;code&gt;wf.wd1/WellsFargoJobs&lt;/code&gt;. Many companies also run several sites: one for experienced hires, one for students, one per country.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. List the jobs
&lt;/h2&gt;

&lt;p&gt;The API lives on the same host, under &lt;code&gt;/wday/cxs/{tenant}/{site}&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl -s https://nvidia.wd5.myworkdayjobs.com/wday/cxs/nvidia/NVIDIAExternalCareerSite/jobs \
  -H &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; \
  -d &lt;span class="s1"&gt;'{"appliedFacets":{},"limit":20,"offset":0,"searchText":"security"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The answer looks like this (shortened):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;413&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"jobPostings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Director, Global Event Security"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;"externalPath"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/job/US-CA-Santa-Clara/Director--Global-Event-Security_JR2023116"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;"locationsText"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"US, CA, Santa Clara"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;"postedOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Posted 30+ Days Ago"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;"bulletFields"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"JR2023116"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"facets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;searchText&lt;/code&gt; is Workday's own keyword search. Leave it empty to get everything. Page through with &lt;code&gt;offset&lt;/code&gt; in steps of 20.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The four gotchas
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pages hold at most 20 jobs.&lt;/strong&gt; Ask for &lt;code&gt;"limit": 50&lt;/code&gt; and you get HTTP 400. Twenty is the maximum.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;total&lt;/code&gt; often comes only with the first page.&lt;/strong&gt; On many sites later pages report &lt;code&gt;0&lt;/code&gt;, so read it from &lt;code&gt;offset: 0&lt;/code&gt; and keep it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Many sites return at most 2,000 jobs per search, and they do not tell you.&lt;/strong&gt; Past offset 2,000 they quietly send the first page again. A loop that stops on an empty page will never stop, and a loop that counts pages will collect the same 20 jobs over and over. These sites also report &lt;code&gt;total: 2000&lt;/code&gt; when they have more: NVIDIA reports 2,000 and has 2,692. Other sites have no such limit. CVS Health reports its real total, about 18,000, and pages through all of it. One request at offset 2,000 tells you which kind you have: if it repeats the first page, the site is capped.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dates are relative.&lt;/strong&gt; The list says "Posted Today" or "Posted 30+ Days Ago". The exact date is only in the job details (next section).&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting past 2,000 on capped sites
&lt;/h3&gt;

&lt;p&gt;The answer also carries &lt;code&gt;facets&lt;/code&gt;: the site's own filters with a job count for each value, such as job family, worker type, time type and location. Pick a facet where every value has fewer than 2,000 jobs, run one search per value, and merge the results by &lt;code&gt;externalPath&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"appliedFacets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"jobFamilyGroup"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;id from facets&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;"offset"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;"searchText"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On very large capped sites one facet is not enough, because even the biggest slice is over 2,000. Then you nest filters: split that slice again by location or worker type.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Job details
&lt;/h2&gt;

&lt;p&gt;Each job's &lt;code&gt;externalPath&lt;/code&gt; gives you the full posting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl -s https://nvidia.wd5.myworkdayjobs.com/wday/cxs/nvidia/NVIDIAExternalCareerSite/job/US-CA-Santa-Clara/Director--Global-Event-Security_JR2023116
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look inside &lt;code&gt;jobPostingInfo&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jobDescription&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full description as HTML&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;startDate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Exact posting date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;location&lt;/code&gt;, &lt;code&gt;additionalLocations&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Every location of the job, not just "2 Locations"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;timeType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full time or part time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;remoteType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Remote, hybrid or on-site, when the company sets it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jobReqId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Requisition ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;externalUrl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Link candidates use to apply&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There is no salary field. US employers publish pay ranges inside the description, in formats like &lt;code&gt;$100,000.00 - $179,000.00&lt;/code&gt;, &lt;code&gt;232,000 USD – 368,000 USD&lt;/code&gt; or &lt;code&gt;USD 120,000 - 150,000&lt;/code&gt;, so you parse them from the text.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. The whole thing in one script
&lt;/h2&gt;

&lt;p&gt;About 90 lines of Python, standard library only. It reads the site from a URL, pages through the search, checks whether the site is capped, splits capped sites by one facet, and prints the first few jobs with details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python workday_jobs_example.py https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite
&lt;span class="c"&gt;# 2692 jobs&lt;/span&gt;
&lt;span class="c"&gt;# Senior QA Engineer, System Product Engineering | Israel, Yokneam | 2026-11-15 | https://nvidia.wd5.myworkdayjobs.com/...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script is on GitHub: &lt;a href="https://github.com/johnkaa/workday-jobs-api" rel="noopener noreferrer"&gt;github.com/johnkaa/workday-jobs-api&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Where to find Workday sites
&lt;/h2&gt;

&lt;p&gt;There is no public list of companies that use Workday. You can build one from the &lt;a href="https://index.commoncrawl.org/" rel="noopener noreferrer"&gt;Common Crawl URL index&lt;/a&gt;: search it for &lt;code&gt;*.myworkdayjobs.com&lt;/code&gt;, collect the tenant and site pairs, and check each one with a single &lt;code&gt;/jobs&lt;/code&gt; request. That is how I put together a list of more than 3,000 live career sites. The 500 biggest are in the same repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Be a good guest
&lt;/h2&gt;

&lt;p&gt;This is public data that companies publish for anyone to read, but it is still somebody's server. Keep a few requests in flight at most, cache what you can, and do not fetch descriptions you do not need.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you would rather not maintain this
&lt;/h2&gt;

&lt;p&gt;I packaged all of the above as &lt;a href="https://apify.com/makerio/workday-jobs" rel="noopener noreferrer"&gt;Workday Jobs Scraper&lt;/a&gt; on Apify. You paste a career site URL or type a company name, or you search one keyword across all 3,000+ sites at once. It handles both kinds of big sites: NVIDIA returns all 2,692 jobs through nested filters, CVS Health all 18,047 by paging straight through. It also parses salaries, filters by location, remote type and posting date, and can return only jobs that are new since the last run. It costs $1.00 per 1,000 jobs. Apify's free plan includes $5 of usage every month, enough for about 5,000 jobs.&lt;/p&gt;

&lt;p&gt;If you also need Greenhouse, Lever, Ashby, SmartRecruiters and other job boards in the same format, &lt;a href="https://apify.com/makerio/career-site-jobs" rel="noopener noreferrer"&gt;Career Site Jobs Scraper&lt;/a&gt; covers nine of them.&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>python</category>
      <category>api</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
